Search code examples
javascripthtmlcss

How to make combined box-shadow of two blocks?


I have two blocks. Let's imagine it's not possible to set one box-shadow for parents of these two blocks. I need to set box-shadow for each blocks, and it must look as if I set it to parent.

body {
  padding: 50px;
}

.block1 {
  padding: 20px;
  border-width: 1px 1px 0 1px;
  border-style: solid;
  border-radius: 4px 4px 0 0;
  border-color: #d5dce3;
  box-shadow: 0 0 2px #00000017,0 5px 25px #0000000a,0 1px 5px #040b170a;
}

.block2 {
  padding: 20px;
  border-width: 0 1px 1px 1px;
  border-style: solid;
  border-radius: 0 0  4px 4px;
  border-color: #d5dce3;
  box-shadow: 0 0 2px #00000017,0 5px 25px #0000000a,0 1px 5px #040b170a;
}
<div class="block1">
  Block 1
</div>
<div class="block2">
  Block 2
</div>

Desired look: enter image description here


Solution

  • Use clip-path to remove the bottom/top shadow from .block1/.block2 like this:

    body {
        padding: 50px;
    }
    
    .block1 {
        padding: 20px;
        border-width: 1px 1px 0 1px;
        border-style: solid;
        border-radius: 4px 4px 0 0;
        border-color: #d5dce3;
        box-shadow: 0 0 2px #00000017,0 5px 25px #0000000a,0 1px 5px #040b170a;
        clip-path: inset(-25px -25px 0 -25px);
    }
    
    .block2 {
        padding: 20px;
        border-width: 0 1px 1px 1px;
        border-style: solid;
        border-radius: 0 0  4px 4px;
        border-color: #d5dce3;
        box-shadow: 0 0 2px #00000017,0 5px 25px #0000000a,0 1px 5px #040b170a;
        clip-path: inset(0 -25px -25px -25px);
    }
    <div class="block1">
      Block 1
    </div>
    <div class="block2">
      Block 2
    </div>

    To get rid of the line between blocks that is caused by a rounding-type error (as mentioned by @AHaworth) we can use a slightly more complex clip-path using polygon (adjust the value 25px if needed, or use a CSS variable):

    body {
        padding: 50px;
    }
    
    .block1 {
        padding: 20px;
        border-width: 1px 1px 0 1px;
        border-style: solid;
        border-radius: 4px 4px 0 0;
        border-color: #d5dce3;
        box-shadow: 0 0 2px #00000017, 0 5px 25px #0000000a, 0 1px 5px #040b170a;
        clip-path: polygon(-25px -25px,
        calc(100% + 25px) -25px,
        calc(100% + 25px) 100%,
        calc(100% - 1px) 100%,
        calc(100% - 1px) calc(100% - 1px),
        1px calc(100% - 1px),
        1px 100%,
        -25px 100%);
    }
    
    .block2 {
        padding: 20px;
        border-width: 0 1px 1px 1px;
        border-style: solid;
        border-radius: 0 0 4px 4px;
        border-color: #d5dce3;
        box-shadow: 0 0 2px #00000017, 0 5px 25px #0000000a, 0 1px 5px #040b170a;
        clip-path: polygon(-25px 0,
        1px 0,
        1px 1px,
        calc(100% - 1px) 1px,
        calc(100% - 1px) 0,
        calc(100% + 25px) 0,
        calc(100% + 25px) calc(100% + 25px),
        -25px calc(100% + 25px));
    }
    <div class="block1">
        Block 1
    </div>
    <div class="block2">
        Block 2
    </div>