I am trying to set up a frame for <img> elements that automatically sizes itself to the inner image and takes its colors from the webpage's CSS variables, consisting of several parts:
--Theme_Outline,2.25rem outside the image on all four sides with square corners and variable-color --Theme_Decor (with the page background visible through the gap), and--Theme_Decor.Here's an example of what I want it to look like that I made in an art program, with a textured background and with pure cyan for variable-color --Theme_Outline and pure red for variable-color --Theme_Decor so they stand out:

The only way I can find to do an inner shadow effect is with a CSS box-shadow with the inset attribute, but that gets rendered beneath the content of whatever element it is attached to (meaning beneath the image in an <img> element, for example), so to make it visible above the image the only option seems to be wrapping the image in a <div> with an ::after pseudo element.
With that constraint (wrapping every <img> in a <div class="bordered">) in mind, the best CSS code I've been able to come up with so far is:
:root{
--Theme_Decor: #ff0000;
--Theme_Outline: #00ffff;
}
html{
position: relative;
box-sizing: border-box;
font-size: 16px;
line-height: 1.5rem;
background-image: url(https://i.sstatic.net/gfRXmBIz.png);
background-size: cover;
background-attachment: fixed;
}
.bordered{
display: inline-block;
position: relative;
padding: 2.25rem;
outline: 0.25rem solid var(--Theme_Outline);
outline-offset: -2.25rem;
border-radius: 2.25rem;
line-height: 0;
}
.bordered::after{
content: "";
position: absolute;
width: calc(100% - 4.5rem);
height: calc(100% - 4.5rem);
inset: 2.25rem;
box-shadow: inset 0 0 0.375rem 0.25rem rgba(0, 0, 0, 0.5);
outline: 0.0625rem solid var(--Theme_Decor);
outline-offset: 2.1875rem;
}
<html>
<div class="bordered">
<img src="https://i.sstatic.net/2fkv9L8M.png">
</div>
</html>
That does what I want for the first three of the four parts of my goal, missing only the corner decorations. Here's a screenshot from Firefox showing the result:

However, I can't figure out a way to insert the corner decorations within the CSS.
If I use url() to link static SVG files inside the content property, I can't find a way to position them at every corner and I can't use stroke="currentColor" or stroke="var(--Theme_Decor)" to get the desired color.
I also experimented with adding the ::before pseudo-element so I could apply the border-image property to it without disrupting the other three parts of the frame, but again couldn't figure out a way to make it pull the desired color.
Is my goal achievable purely with CSS? Or do I need to settle for adding extra HTML elements around every <img> that I want to be framed?
For completeness, here is the SVG code for the individual corner decorations, using the color black as a placeholder:
<svg id="UIT_Corner_Image_TopLeft" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28" width="28px">
<path d="M.5,27.5h1c3.86599325,0,7-3.13400675,7-7v-12h12c3.86599325,0,7-3.13400675,7-7V.5" fill="none" stroke="#000"/>
</svg>
<svg id="UIT_Corner_Image_TopRight" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 108 72" width="108px">
<path d="M107.5,8.5l-100-0c-3.86599325,0-7-3.13400675-7-7V.5" fill="none" stroke="#000"/>
<path d="M38.23828125,8.5c2.515625,4.75579834,7.50708008,8,13.26171875,8h40v40c0,8.28424072,6.71569823,15,15,15h1" fill="none" stroke="#000"/>
</svg>
<svg id="UIT_Corner_Image_BottomLeft" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 108 72" width="108px">
<path d="M.5,63.5h100c3.86599325,0,7,3.13400676,7,7v1" fill="none" stroke="#000"/>
<path d="M69.76171875,63.5c-2.515625-4.75579834-7.50708008-8-13.26171875-8H16.5V15.5c0-8.28424072-6.71569824-15-15-15H.5" fill="none" stroke="#000"/>
</svg>
<svg id="UIT_Corner_Image_BottomRight" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28" width="28px">
<path d="M27.5.5h-1c-3.86599325,0-7,3.13400675-7,7v12H7.5c-3.86599325,0-7,3.13400675-7,7v1" fill="none" stroke="#000"/>
</svg>
And here is the SVG code for the border-image version:
<svg id="UIT_Border_Image" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 224 160" width="224" height="160">
<g opacity="0.75">
<path d="M.5,27.5h1c3.86599325,0,7-3.13400675,7-7v-12h12c3.86599325,0,7-3.13400675,7-7V.5" fill="none" stroke="#000"/>
<path d="M223.5,8.5h-100c-3.86599325,0-7-3.13400675-7-7V.5" fill="none" stroke="#000"/>
<path d="M154.23828125,8.5c2.515625,4.75579834,7.50708008,8,13.26171875,8h40v40c0,8.28424072,6.71569824,15,15,15h1" fill="none" stroke="#000"/>
<path d="M.5,151.5h100c3.86599325,0,7,3.13400676,7,7v1" fill="none" stroke="#000"/>
<path d="M69.76171875,151.5c-2.515625-4.75579834-7.50708008-8-13.26171875-8H16.5v-40c0-8.28424072-6.71569824-15-15-15H.5" fill="none" stroke="#000"/>
<path d="M223.5,132.5h-1c-3.86599325,0-7,3.13400675-7,7v12h-12c-3.86599325,0-7,3.13400675-7,7v1" fill="none" stroke="#000"/>
</g>
</svg>
Plus an example of the CSS I came up with for using the border-image property, though using a PNG version because I couldn't find a way to reference the SVG file within the code snippet:
:root{
--Theme_Decor: #ff0000;
--Theme_Outline: #00ffff;
}
html{
position: relative;
box-sizing: border-box;
font-size: 16px;
line-height: 1.5rem;
background-image: url(https://i.sstatic.net/gfRXmBIz.png);
background-size: cover;
background-attachment: fixed;
}
.bordered{
display: inline-block;
position: relative;
padding: 2.25rem;
outline: 0.125rem solid var(--Theme_Outline);
outline-offset: -2.25rem;
border-radius: 2.25rem;
line-height: 0;
}
.bordered::before{
content: "";
position: absolute;
width: calc(100% - 4.5rem);
height: calc(100% - 4.5rem);
left: 0;
top: 0;
border-style: solid;
border-color: rgba(0, 0, 0, 0);
border-width: 2.25rem 2.25rem;
border-image-source: url(https://i.sstatic.net/Ums6HqNE.png);
border-image-slice: 72 108;
border-image-width: 4.5rem 6.75rem;
outline: 0.0625rem solid var(--Theme_Decor);
outline-offset: -0.0625rem;
}
.bordered::after{
content: "";
position: absolute;
width: calc(100% - 4.5rem);
height: calc(100% - 4.5rem);
inset: 2.25rem;
box-shadow: inset 0 0 0.375rem 0.25rem rgba(0, 0, 0, 0.5);
}
<html>
<div class="bordered">
<img src="https://i.sstatic.net/2fkv9L8M.png">
</div>
</html>
Here is an idea using mask where you can easily control the color by setting background. I am including the SVG as data images but you can also reference them as url if you want.
.bordered {
--Theme_Decor: #ff0000;
--Theme_Outline: #00ffff;
display: inline-flex;
position: relative;
padding: 2.25rem;
outline: 0.125rem solid var(--Theme_Outline);
outline-offset: -2.25rem;
border-radius: 2.25rem;
}
.bordered img {
outline: 0.0625rem solid var(--Theme_Decor);
outline-offset: 2.25rem;
}
.bordered::before {
content: "";
position: absolute;
inset: 0;
background: var(--Theme_Decor); /* color of SVG here */
mask:
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28"><path d="M.5,27.5h1c3.86599325,0,7-3.13400675,7-7v-12h12c3.86599325,0,7-3.13400675,7-7V.5" fill="none" stroke="black"/></svg>') 0 0,
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 108 72"><path d="M107.5,8.5l-100-0c-3.86599325,0-7-3.13400675-7-7V.5" fill="none" stroke="black"/><path d="M38.23828125,8.5c2.515625,4.75579834,7.50708008,8,13.26171875,8h40v40c0,8.28424072,6.71569823,15,15,15h1" fill="none" stroke="black"/></svg>') 100% 0,
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 108 72" width="108px"><path d="M.5,63.5h100c3.86599325,0,7,3.13400676,7,7v1" fill="none" stroke="black"/><path d="M69.76171875,63.5c-2.515625-4.75579834-7.50708008-8-13.26171875-8H16.5V15.5c0-8.28424072-6.71569824-15-15-15H.5" fill="none" stroke="black"/></svg>') 0 100%,
url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28"><path d="M27.5.5h-1c-3.86599325,0-7,3.13400675-7,7v12H7.5c-3.86599325,0-7,3.13400675-7,7v1" fill="none" stroke="black"/></svg>') 100% 100%;
mask-size: 2rem auto, 6rem auto, 6rem auto, 2rem auto; /* size of the SVG here */
mask-repeat: no-repeat;
}
.bordered::after {
content: "";
position: absolute;
inset: 2.25rem;
box-shadow: inset 0 0 0.375rem 0.25rem rgba(0, 0, 0, 0.5);
}
html {
background: url(https://i.sstatic.net/gfRXmBIz.png) 50%/cover fixed;
}
img {
width: 200px;
}
<div class="bordered">
<img src="https://i.sstatic.net/2fkv9L8M.png">
</div>
<div class="bordered" style="--Theme_Decor: blue">
<img src="https://i.sstatic.net/2fkv9L8M.png">
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With