2

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:

  • an inner shadow on all edges of the image,
  • an outer border with rounded corners and variable-color --Theme_Outline,
  • an offset border 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
  • four SVG decorations (one at each corner of the offset border) with variable-color --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:

Example image made in an art program

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:

Image captured from browser with everything except the corner decorations

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?

President Jam
1,2081 gold badge6 silver badges22 bronze badges
asked 12 hours ago
5
  • 1
    I've tried to rebuild what you say you have, and start finding a solution from there, but I cannot get what you already have. That makes it hard to help you. Please see: How to create a Minimal, Reproducible Example. Try to make a code snippet. People here on Stack Overflow really like clear, concise, to the point, and complete questions. Commented 11 hours ago
  • For the corner decoration, look at stackoverflow.com/questions/51402532/…. As long as the SVG is part of the DOM, you can style whatever you position in the corners with CSS. Having it in a separate file or a data URL blocks the styling. Does that answer your question? Commented 11 hours ago
  • @KIKOSoftware Adding the color variables to your CodePen makes it match what I've got. I added them to the code in my question for clarity. Commented 10 hours ago
  • @ccprog My question is, is there a way to insert the decorations with CSS in a way that doesn't block the styling? Commented 8 hours ago
  • can you share the SVG part? Commented 2 hours ago

1 Answer 1

-1

You can achieve a combination of inner shadow, rounded borders, and offset borders using a combination of box-shadow, border-radius, and pseudo-elements in pure CSS.

Here’s an approach that works across browsers without visual glitches:

<div class="fancy-box">
 <div class="fancy-inner"></div>
</div>
.fancy-box {
 position: relative;
 width: 200px;
 height: 120px;
 border-radius: 20px;
 border: 3px solid #4CAF50; /* outer rounded border */
 background: #fff;
 box-shadow: 0 4px 8px rgba(0,0,0,0.15); /* outer drop shadow */
 overflow: hidden;
}
/* Inner shadow via pseudo-element */
.fancy-box::before {
 content: "";
 position: absolute;
 inset: 0;
 border-radius: inherit;
 box-shadow: inset 0 4px 8px rgba(0,0,0,0.2); /* inner shadow */
 pointer-events: none;
}
/* Optional offset border effect */
.fancy-box::after {
 content: "";
 position: absolute;
 inset: -6px; /* adjust for ‘offset’ effect */
 border-radius: calc(20px + 6px);
 border: 2px solid rgba(76, 175, 80, 0.4);
 pointer-events: none;
}

Explanation

  • border-radius ensures smooth, rounded edges.

  • The ::before pseudo-element creates an inner shadow using inset box-shadow and matches the same radius.

  • The ::after pseudo-element is an offset border, visually sitting outside the main box without overlapping.

  • pointer-events: none ensures these layers don’t block interactions.

Notes

  • This method avoids "ugly corner" artifacts that happen when combining border-radius and inset box-shadow directly on the same element.​

  • If you need multiple shadow layers (both inner and outer), you can list them:
    box-shadow: inset 0 2px 5px rgba(0,0,0,0.15), 0 4px 8px rgba(0,0,0,0.25);.​

  • Works well on modern browsers and scales responsively.

This layered pseudo-element method allows you to simulate Photoshop-like combinations of rounded borders, inner shadows, and offset outlines using pure CSS.

answered 54 mins ago
New contributor
ewangewang is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.