I worked on a website where many images should have an inner shadow. To not need to edit all of them in Photoshop, the “inset” value for the CSS3 attribute “box-shadow” came in handy, but it cannot be applied to images without more ado. I want to show my solution here.
Applied directly on img
elements, the shadow stays behind the image, so it is only visible at all if the image has transparency. If you add a wrapper element which gets the shadow, it is still behind the image but can be positioned with z-index
. Unfortunately the image has to be moved to the back, moving the wrapper to the front is not possible 1:
1) Wrapper with Box Shadow, Image in The Background
HTML
<div class="box-shadow"> <img src="/images/graphic.jpg" /> </div>
CSS
.box-shadow { box-shadow: 0 0 10px 6px white inset; } .box-shadow img { position: relative; z-index: -1; }
The problem with this code is that the image is not only placed behind the wrapper but behind all other elements in the same Stacking Context. Which elements form a stacking context is described quite well in the Mozilla Documentation:
- the root element (HTML),
- positioned (absolutely or relatively) with a z-index value other than “auto”,
- a flex item with a z-index value other than “auto”,
- elements with an opacity value less than 1. (See the specification for opacity),
- elements with a transform value other than “none”,
- elements with a mix-blend-mode value other than “normal”,
- elements with isolation set to “isolate”,
- on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is “auto”
- specifing any attribute above in will-change even you don’t write themselves directly
2) Stacking Context
In this case it was applicable to assign a z-index and relative positioning to the direct parent element of the wrapper (let’s call it #parent
):
CSS
#parent { position: relative; z-index: 0; }
If this is not possible, e.g. because it needs a different position value or the z-index has unwanted side effects, I would use opacity instead, with a value of almost 1, so that no effect is visible but it still creates a stacking context.
CSS (alternativ)
#parent { opacity: 0.999; }
Related post on StackOverflow Continue reading “[CSS] Inset Box Shadow On Image”
Notes:
- Can anybody explain why? Obviously I still don’t 100% get z-index. ↩