50

I don't understand why, but an inset box shadow is beneath my content.

Here's an example:

div {
   box-shadow:inset 0 0 10px black;
   height:300px;
   color:red;
}
<div>
   a
</div>

http://jsfiddle.net/MAckM/

You see the a is on top of the box shadow.

How can I get the box shadow to be on top of the a?

TylerH
  • 20,799
  • 66
  • 75
  • 101
henryaaron
  • 6,042
  • 20
  • 61
  • 80
  • I already used this olution works great, but additionaly inportant thing is z-index of this div:before. Don't forget to use it when You have trouble to cover full content. – Kordian Wikliński Dec 15 '14 at 08:44

2 Answers2

49

You need to make a new element inside the div, with absolute positioning and height and width of 100%, then give that element the box shadow.

div {
    height: 300px;
    color: red;
    position: relative;
}

div > div {
    box-shadow: inset 0 0 10px black;
    position: absolute;
    pointer-events: none;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
<div>
    <div></div>
    Sample text
</div>

Alternatively, you can use a pseudo-element:

div {
    height: 300px;
    color: red;
    position: relative;
}

div:before {
    content: '';
    box-shadow: inset 0 0 10px black;
    position: absolute;
    pointer-events: none;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}​
<div>
    Sample text
</div>​
BlueManCZ
  • 417
  • 6
  • 12
fncombo
  • 1,202
  • 1
  • 12
  • 14
  • 2
    In modern browsers (incl. IE9+), generated content (`:before`, `:after`) can be used instead of a real element. (IE8 does support generated content too, but has a bug preventing generated content to be above real content, and of course does not support CSS box shadow itself.) – Marat Tanalin Nov 02 '12 at 18:14
  • @MaratTanalin Absolutely right. And its a much more beautiful solution, too. Updated the answer. – fncombo Nov 02 '12 at 18:20
  • Either answer is fine by me, but I have a problem. When I have another `div` inside the central `div` the shadow element or pseudo class lays on top of the inner `div`. If I add a z-index to the inner div, then it goes on top of the box-shadow. Try to click on the link in this demo: http://jsfiddle.net/MAckM/5/ – henryaaron Nov 02 '12 at 20:24
  • Another way would be to create 4 separate elements with linear gradients and position them on the edges, to mimic what a box shadow would look like. But if IE support is what you're looking for, I'm afraid that won't do either. – fncombo Nov 06 '12 at 00:40
  • Yes, I thought that would be other way :(. Thanks – henryaaron Nov 07 '12 at 01:14
  • 2
    Apparently, for the containers that have scrollable content, it's better to use the empty `div`, as `:before` will make the shadow scroll with the content. – Eugene Pakhomov Mar 17 '17 at 14:30
  • 2
    For me, the div solution also make the shadow scrolling. Plus, I lose my parent padding to adjust content. – Robouste Sep 04 '17 at 10:01
  • @fncombo can you please review this question about your solution? https://stackoverflow.com/questions/49652744/inset-box-shadow-beneath-content-scroll-fix – medk Apr 04 '18 at 13:52
  • Should really be an :after if you want it to appear above the other div (sibling) contents as dom elements are stacked on top by default. Of course you could apply a z-index to the before but seems cleaner as an :after – Jon Catmull Jan 27 '19 at 16:17
  • 1
    I would suggest adding ``pointer-events: none;`` as in Michael Plotke's answer. – cyclingLinguist Mar 21 '22 at 18:09
6

This answer offers the most straightforward solution via a minimal example and addresses the issue of scrolling.

Unfortunately there is no way to avoid an extra wrapping div (due to box-shadow layering).

.container {
  position: relative;
}

.container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  box-shadow: inset 0 0 9px 3px yellow;
  pointer-events: none;
}

.items {
  height: 100px;
  overflow: scroll;
}
<div class="container">
  <div class="items">
    <div class="item">One</div>
    <div class="item">Two</div>
    <div class="item">Three</div>
    <div class="item">Four</div>
    <div class="item">Five</div>
    <div class="item">Six</div>
    <div class="item">Seven</div>
    <div class="item">Eight</div>
    <div class="item">Nine</div>
    <div class="item">Ten</div>
    <div class="item">Eleven</div>
    <div class="item">Twelve</div>
  </div>
</div>
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Michael Plotke
  • 951
  • 1
  • 15
  • 38