Here is my html and css code:
.image-box{
max-width: 300px;
position: relative;
}
.image-box img{
max-width: 100%;
width: 100%;
object-fit: cover;
border: 8px solid #000000;
border-right: 0;
border-bottom: 0;
/* border-image: linear-gradient(to right, #000 68%, transparent 32%) 100% 1; */
}
<div >
<figure>
<img src="https://via.placeholder.com/300" alt="">
</figure>
</div>
While running this, I receive this.
But, I want to have something like this:
If I uncomment this line
border-image: linear-gradient(to right, #000 68%, transparent 32%) 100% 1;
Then it shows half width border on top, but this also make the left border disappear and show like this.
CodePudding user response:
You can do something like this using pseudo classes to make the border at the top like how you want it to be achieved:
What it does is hide the half of the border at the top.
.box {
width: 150px;
height: 150px;
background-color: black;
border-top: 5px solid red;
border-left: 5px solid red;
position: relative;
}
.box:after {
content: "";
width: 50%;
height: 5px;
background-color: white;
position: absolute;
right: 0;
top: -5px;
}
<div ></div>
CodePudding user response:
Disclaimer: Not an exhaustive list. Try to come up with yet another solution!
With background-image: linear-gradient()
To make a linear-gradient look like a border, we can add padding to the image and a hard color-stop to the gradient:
.image-box {
--thickness: 8px;
}
.image-box img {
padding-top: var(--thickness);
padding-left: var(--thickness);
background-image: linear-gradient(to right, black 60%, white 60%);
}
figure{margin:0;line-height:0}
<div >
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
A potential problem with this is that only one side of the border may be shorter.
With Pseudo-elements
Pseudo-elements can be used for presentational styling. You can easily identify them in your CSS by their double-colons (e.g. ::before
, ::marker
).
Sidenote: While still supported for legacy reasons, they can also be written with a single-colon (e.g. :before
). Do yourself a favour and use the double-colons.
We can use pseudo-elements to create the border.
I will use custom properties to make the code easier to change.
Personally, I enjoy the method Placing behind the most, because that way no bleeding through of the parent's background should happen in extreme (zoom) cases.
Composition
Composite the border with ::before
for the left and ::after
for the top side. Since these are separate elements, we can define their width and height individually:
.image-box::before, .image-box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: black;
}
.image-box::before { /* Left */
width: var(--thickness);
height: 100%;
}
.image-box::after { /* Top */
width: 60%;
height: var(--thickness);
}
.image-box {
--thickness: 8px;
position: relative;
/* Leave space for border */
padding-top: var(--thickness);
padding-left: var(--thickness);
max-width: 300px;
box-sizing: border-box;
}
.image-box img {max-width:100%}
figure{margin:0;line-height:0}
<div >
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
Placing behind
Place the image on top of a pseudo-element to make it look like a (partially wide) border:
.image-box::before, .image-box>figure {
grid-area: 1/1 / 1/1; /* Place both on first grid-cell */
}
.image-box::before {
content: "";
width: 60%;
height: 100%;
background-color: black;
}
.image-box {
--thickness: 8px;
max-width: 300px;
display: grid;
}
.image-box img {
/* Leave space for border */
padding-top: var(--thickness);
padding-left: var(--thickness);
width: 100%;
box-sizing: border-box;
}
figure{margin:0;line-height:0}
<div >
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
Using clip-path: polygon()
Specify each point of the "top-left corner" shape in polygon()
:
.image-box {
position: relative;
padding-top: 8px;
padding-left: 8px;
max-width:300px;
}
.image-box::before {
--thickness: 8px;
content: "";
position: absolute;
top: 0;
left: 0;
width: 60%;
height: 100%;
clip-path: polygon(
0 0,
100% 0,
100% var(--thickness),
var(--thickness) var(--thickness),
var(--thickness) 100%,
0 100%);
background-color: black;
}
figure {margin:0;line-height:0}
<div >
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
Why not use border
?
Edit: Apparently border-image
is a thing. See an example. Bottom section is therefore outdated.
Unfortunately, each side of a border can only be a single color. This means the black & white top border is not possible by only using the border
property.
A solution to this would be to redraw over part of the border that we don't want:
#example {
padding: 1rem;
background-color: slateblue;
}
.image-box {
--thickness: 8px;
position: relative;
border: 0 solid black;
border-top-width: var(--thickness);
border-left-width: var(--thickness);
max-width: 300px;
}
.image-box::after {
content: "";
position: absolute;
top: calc(-1 * var(--thickness));
right: 0;
/* 100% - <length> <thickness left-side> */
width: calc(100% - 60% var(--thickness));
height: var(--thickness);
background-color: white;
}
body {
display: flex;
flex-direction: column;
gap: 1rem;
}
figure{margin:0;line-height:0}
<div >
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
<div id="example">
<div >
<figure>
<img src="https://via.placeholder.com/300">
</figure>
</div>
</div>
But as you can see, this way we will lose the background of the parent. Hard-coding some color only works if the parent's background is a solid color. If the parent's background is an image, this won't work.
Also, having to tell .image-box
the color to draw over with is redundant information (because the background already exists) and would only cause more mental overhead for the developer.
CodePudding user response:
you are almost good with border-image. You need to correctly define the slice.
.image-box {
max-width: 300px;
position: relative;
}
.image-box img {
max-width: 100%;
width: 100%;
object-fit: cover;
border: 8px solid #000000;
border-right: 0;
border-bottom: 0;
border-image: linear-gradient(to right, #000 68%, transparent 32%) 1;
}
<div >
<figure>
<img src="https://via.placeholder.com/300" alt="">
</figure>
</div>