'Why doesn't inset box-shadow work over images?

I have a container that uses inset box shadow. The container contains images and text. The inset shadow apparently does not work on images:

The problem

The white section here is the container. It contains a white image, and there is inset box shadow applied to it.

<main>
    <img src="whiteimage.png">
</main>
body {
    background-color: #000000;
}

main {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 90%;
    height: 90%;
    background-color: #FFFFFF;
    box-shadow: inset 3px 3px 10px 0 #000000;
}

Is there a way to make the inset box shadow overlap images?

Live demo

css


Solution 1:[1]

Just to chime in on this, because I was just creating something similar...

I hate polluting my markup with extra elements for the sake of styling, so the CSS solution is to use the :after pseudo element:

main::after
{
 box-shadow: inset 3px 3px 10px 0 #000000;
 content: '';
 display: block;
 height: 100%;
 position: absolute;
 top: 0;
 width: 100%;
}

It's probably too late for what you were trying to do, but is the better solution in my estimation.

Solution 2:[2]

The reason it's not overlapping is because the image is inside the div, so the image is on top of it. The image is higher (closer to the user) than the div.

You can change the image to use position: relative; z-index: -1, and have the containing div use a border instead of setting background color on the body. You'll need to use box-sizing: border-box to include the border in the width of the div.

DEMO

body {
    background-color: #FFF;
}

main {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 100%;
    height: 100%;
    border: 60px solid black;
    box-shadow: inset 3px 3px 10px 0 #000000;
    box-sizing: border-box;
}

img {
    z-index:-1;
    position: relative;
}

Solution 3:[3]

For those, who're using absolute-positioned, full-size :before/:after pseudo elements, consider using pointer-events: none on the pseudo-element so the original elements remain clickable.

Solution 4:[4]

You could set the image as the div's background instead:

background-image:url(http://www.placehold.it/500x500)

jsFiddle example

Solution 5:[5]

https://stackoverflow.com/a/21415060/6235358 that's a great way to do it but we can do it in a better way using the ::after pseudo-class so you'll not have to add an empty <div> to your HTML

Solution 6:[6]

The best way to achieve this in 2020 would be to use mix blend mode on the image. use the box-shadow on the parent element of the img and use mix-blend-mode: multiply.

Solution 7:[7]

One simple fix if you are clever with your decimals is to store your content in a separate div which you then select and implement a certain number of pixels from the top.

For example, let's say your header has a height of 50px. You could begin your #content div id 53.45px from the top (or whatever height your drop shadow is) and then your shadow would appear above the images.

One issue with this is that if you are using a rather transparent shadow, the more transarent it is the more tacky it may look by implementing this css.

In practice the code would be as follows:

HTML:

  <header>
Whatever's in your header
</header>

<div id="content>
Page content
</div>

CSS:

header {
    height: 50px;
    box-shadow: 0 5px 5px rgba(0,0,0,1);
}

#content {
    top: 55px;
}

Solution 8:[8]

As Rilus mentioned we could use a pseudo class. Unfortunately this does not seem to work on an img tag for some reason however we can use a combination of inner and outer containers to achieve the affect we need.

.outer:hover .inner:after {
position: absolute;
content: '';
color: white;
display:block;
bottom: -0px;
right: -0px;
width: 100%;
height: 100%;
z-index: 11;
border: solid 10px red;
}

http://jsbin.com/kabiwidego/1/

not sure about ie 10 though as it seems to handle pseudo classes that are absolutely positioned slightly differently to most browsers.

Solution 9:[9]

Even if i'm late for the party, I had the same issue these days and worked on a solution. For me, the best solution (mobile friendly) is this one:

JSFiddle:

.image-inset-container {
  margin-bottom: 30px;
}

.image-inset-shadow {
  position: relative;
}

.image-inset-shadow img {
  border-radius: 20px;
}

.image-shadow {
  position: absolute;
  width: 100%;
  height: 100%;
  box-shadow: inset 3px 3px 10px 0 #000;
  border-radius: 20px;
  top: 0;
  left: 0;
}
<body>
  <h4>Reimagined Web Design</h4>
  <p>With your input and business goals in mind, we bring your brand to life through custom human-facing graphics and
    visual elements targeted toward your audience for good user experience and created in future-forward technology,
    guaranteeing a successful new web design.</p>
  <div class="image-inset-container">
    <div class="image-inset-shadow"><img src="https://upload.wikimedia.org/wikipedia/commons/d/d2/Solid_white.png" alt="img1" />
      <div class="image-shadow"></div>
    </div>
  </div>
  <p>We initiate a collaborative process where your team is involved in every step to create a frictionless and
    delightful
    experience for your customers. Our designers immerse themselves in your industry and your brand aesthetic to
    deliver
    a website that represents your business while achieving your goals for a connected future.</p>
</body>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 John
Solution 2 brouxhaha
Solution 3
Solution 4 j08691
Solution 5 Mathieu Ferraris
Solution 6 Prakhar Thakur
Solution 7 James Lewis
Solution 8
Solution 9 Claude Dumont