Last update:

CSS shadows under adjacent elements

The problem

Having several elements close to each other and applying a box shadow on them may cause the shadow from an element to render on top of the previous element, like this:

See the Pen Overlapping shadows

This is caused by the fact that the shadow of an element is tied to it and nothing can be inserted between a box and its shadow. This, of course, may be perfectly fine in some cases, but let’s focus on changing this behavior – we would like to have shadows under all element.

Shadows under elements

To overcome this, we’ll have to somehow separate the element and its shadow. Fortunately, CSS makes it possible with pseudoelements. We’ll render the shadow in a pseudoelement (could be either before or after, it doesn’t matter) and assign a negative z-index to it. It is important that the element itself does not have a z-index property (or has it set to auto):

The :before pseudoelement is a box that has the same size as the original element, but thanks to the lower z-index, it is rendered below other elements.

See the Pen Fixed overlapping shadows1

“All right, but why can’t we set any z-index to the original element?” – you may ask. The reason is that setting the z-index creates a new local static context and elements from these contexts can’t be interwoven.

Why would I need it?

For example, to create complex interfaces with drop shadows:

See the Pen Complex layout1

Throw in some border radius to create even more crazy stuff:

See the Pen Large box vertices1

Browser support?

I tested it in IE >=9, latest Chrome and Firefox on Windows and I didn’t spot any problems. Older IEs don’t support box-shadow, so nope.


  1. Hey, I just wanted to let you know that you were a huge help! I was using some pseudo-material design with an interactive box, with multiple buttons, making up the bottom. Thanks to this post, I was able to fix the shadowing on it!

    Irvin Shen on 16 January 2018, 11:38 +01:00 Reply
    1. I’m glad I could help!

      Michał Dudak on 16 January 2018, 11:54 +01:00 Reply
  2. I found this post to be very informative and helpful. I will have to recommend you to my friends. I am very thankful to you for giving this post.

    Tylor on 31 May 2018, 5:58 +01:00 Reply
  3. Wow! the first one codepen is a very simple and really awesome solution! it costs me the whole working day before . decided to look up in google and founf yours!!
    really helpful) thanks a lot!

    and i have more interesting task: to make outer-rounded corners inbetween.. right where i put stars
    | ___ ____ |
    | ( * ) ( * ) |
    |__| |__| |__|

    hope you understood what i mean..)
    Anyway I’ll fork your codepen and try to find easy solution. you inspired me. thanks a lot)

    Irena on 13 July 2018, 1:43 +01:00 Reply
  4. Thanks so much for this. Worked like a charm. Very useful info. Bookmarked for future in case I forget!

    Stephen Price on 20 September 2018, 17:29 +01:00 Reply
  5. Dzięki wielkie. Męczyłem się właśnie z pewnym menu z przyciskami podbitym cieniami, kombinowałem z z-indexami i cały czas fiasko. Ten artykuł bardzo pomógł.

    Greg on 15 December 2018, 1:57 +01:00 Reply
  6. I am trying to add animation for the element, I forked your playground but it did not work.
    Do you have any idea?

    Sorcerer on 22 February 2019, 6:17 +01:00 Reply
  7. Thanks a lot! 🙂

    antonino on 26 June 2019, 9:09 +01:00 Reply
  8. Hey this is suuuper helpful and I have come back to use this guide twice now. Very nice!

    Taylor Love on 4 January 2020, 22:40 +01:00 Reply
  9. Thanks for this, it’s been a huge help with my latest small project on CodePen using Neumorphism! Still a work in progress but check it out if you want 🙂

    Gavin on 6 March 2020, 23:53 +01:00 Reply
  10. Thanks🤘

    Sanjesh Sharma on 18 March 2020, 16:39 +01:00 Reply
  11. You sir are a life saver and a genius!

    Thanks 3000!

    Krisztian Dobo on 11 April 2020, 18:52 +01:00 Reply
  12. Just in case this catches anyone else, be aware that your pseudo element will be on top of the main element and so to be on the safe side, you might need to add pointer-events: none e.g.

    .withShadow:before {
    content: “”;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: -1;
    box-shadow: -5px 5px 20px 5px #000;
    pointer-events: none;

    Julian Jelfs on 6 January 2021, 10:35 +01:00 Reply
  13. You’re a fucking genius… Thank you!!

    Kevv on 29 January 2021, 21:50 +01:00 Reply
  14. You just saved my day. Thanks!!!

    morninlark on 2 March 2021, 16:58 +01:00 Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Michał Dudak