Search code examples
cssbox-shadow

Box-Shadow on only specific borders of 3 divs


It's been a couple hours already that I am struggling with my CSS.

I'm trying to add a box-shadow on an element of my website that is composed of 3 divs : #top #content and #bot.

Here is a picture to help you visualize what I deal with : enter image description here

Having the box-shadow on the left and right of the div #content was kind of the easy part, but I'm really struggling for the top and bottom part. I can't make anything that looks decently clean.

Here is my code :

body {
  margin-top: 30px;
}
div#content {
  padding: 20px 30px 20px 30px;
  color: #515348;
  font-size: 76%;
  line-height: 1.6em;
  height: 100px;
  background: #FFF;
  width: 240px;
  margin-right: auto;
  margin-left: auto;
  border-left: 1px solid grey;
  border-right: 1px solid grey;
  box-shadow: 0 9px 0px 0px white, 0 -9px 0px 0px white, 8px 0 14px -4px rgba(33, 33, 33, 0.6), -8px 0 14px -4px rgba(33, 33, 33, 0.5);
}
#top {
  background: #FFF;
  height: 10px;
  width: 300px;
  margin: 0 auto;
  position: relative;
  -webkit-border-radius: 8px 8px 0px 0px;
  -moz-border-radius: 8px 8px 0px 0px;
  border-radius: 8px 8px 0px 0px;
  behavior: url(/PIE.htc);
  border-top: 1px solid grey;
  border-left: 1px solid grey;
  border-right: 1px solid grey;
  box-shadow: 0 9px 0px 0px white, -8px 0 14px -4px rgba(33, 33, 33, 0.5), 8px 0 14px -4px rgba(33, 33, 33, 0.6), -8px 0 14px -4px rgba(33, 33, 33, 0.5);
}
#bot {
  background: #FFF;
  height: 10px;
  width: 300px;
  margin: 0 auto;
  position: relative;
  -webkit-border-radius: 0px 0px 8px 8px;
  -moz-border-radius: 0px 0px 8px 8px;
  border-radius: 0px 0px 8px 8px;
  behavior: url(/PIE.htc);
  border-bottom: 1px solid grey;
  border-left: 1px solid grey;
  border-right: 1px solid grey;
  box-shadow: 8px 4px 14px 4px rgba(33, 33, 33, 0.5), 0 9px 0px 0px white, 8px 0 14px -4px rgba(33, 33, 33, 0.6), -8px 0 14px -4px rgba(33, 33, 33, 0.5);
}
<div id="top"></div>
<div id="content"></div>
<div id="bot"></div>

Any idea about making this thing a bit "cleaner" ?

Quick Edit: The box-shadow on the bot part actually didn't look that bad on my screen, i had found some better settings that I since lost by trying different configurations.


Solution

  • Shadow all around the shape:

    The image provided in question (when seen along with the snippet) is a bit confusing on whether you are looking for a shadow on only the sides (or) for the entire shape as a whole.

    If you are looking to add a shadow to the entire shape then one option is to add one pseudo-element to the container element such that it is equal to the height of the container + the top + the bottom element. This pseudo-element should also be given border-radius and be positioned above the container by the same no. of pixels as the height of the top element (inversed). Adding the required box-shadow to this pseudo-element will produce the expected output.

    body {
      margin-top: 30px;
    }
    div#content {
      position: relative;
      height: 100px;
      width: 240px;
      padding: 20px 30px 20px 30px;
      margin-right: auto;
      margin-left: auto;
      color: #515348;
      font-size: 76%;
      line-height: 1.6em;
      background: #FFF;
      border-left: 1px solid grey;
      border-right: 1px solid grey;
    }
    div#content:before {
      position: absolute;
      content: '';
      left: 0px;
      top: -10px;  /* positioning above makes shadow extend above */
      height: calc(100% + 20px);  /* to offset for top and bottom */
      width: 100%;
      border-radius: 8px;
      z-index: -1;  /* to send the elements and their shadow behind  */
      box-shadow: 6px 0px 6px 0px rgba(33, 33, 33, 0.25), -6px 0px 6px 0px rgba(33, 33, 33, 0.25), 0px 6px 6px 0px rgba(33, 33, 33, 0.25), 0px -6px 6px 0px rgba(33, 33, 33, 0.25);
    }
    #top {
      position: relative;
      height: 10px;
      width: 300px;
      margin: 0 auto;
      background: #0F0;
      border-radius: 8px 8px 0px 0px;
      border: 1px solid grey;
      border-width: 1px 1px 0px 1px;
    }
    #bot {
      position: relative;
      height: 10px;
      width: 300px;
      margin: 0 auto;
      background: #00F;
      border-radius: 0px 0px 8px 8px;
      border: 1px solid grey;
      border-width: 0px 1px 1px 1px;
    }
    <div id="top"></div>
    <div id="content"></div>
    <div id="bot"></div>


    Shadow all around shape but fades towards top and bottom:

    In this approach the shadow is applied all around the shape but it gradually fades towards the top and bottom. These are all the possible variants based on description, image in question and snippet. You can choose the one which suits you best.

    body {
      margin-top: 30px;
    }
    div#content {
      position: relative;
      height: 100px;
      width: 240px;
      padding: 20px 30px 20px 30px;
      margin-right: auto;
      margin-left: auto;
      color: #515348;
      font-size: 76%;
      line-height: 1.6em;
      background: #FFF;
      border-left: 1px solid grey;
      border-right: 1px solid grey;
    }
    div#content:before {
      position: absolute;
      content: '';
      left: 0px;
      top: -8px;  /* positioning above makes shadow extend above */
      height: calc(100% + 16px);  /* to offset for top and bottom */
      width: 100%;
      border-radius: 8px;
      z-index: -1;  /* to send the elements and their shadow behind  */
      box-shadow: 6px 0px 6px 0px rgba(33, 33, 33, 0.25), -6px 0px 6px 0px rgba(33, 33, 33, 0.25), 0px 0px 6px 0px rgba(33, 33, 33, 0.25), 0px 0px 6px 0px rgba(33, 33, 33, 0.25);
    }
    #top {
      position: relative;
      height: 10px;
      width: 300px;
      margin: 0 auto;
      background: #0F0;
      border-radius: 8px 8px 0px 0px;
      border: 1px solid grey;
      border-width: 1px 1px 0px 1px;
    }
    #bot {
      position: relative;
      height: 10px;
      width: 300px;
      margin: 0 auto;
      background: #00F;
      border-radius: 0px 0px 8px 8px;
      border: 1px solid grey;
      border-width: 0px 1px 1px 1px;
    }
    <div id="top"></div>
    <div id="content"></div>
    <div id="bot"></div>


    Shadow only on sides:

    Looking closely at the original image provided in the question, one thing that I can see is that you don't actually need a box-shadow on the top and bottom elements. You just need shadow on the container which extends a little above and below it. This can be achieved in a very hacky way by using just the container element alone but that's just way too complex and ugly.

    So, the alternate option is to add one pseudo-element to the container element and position it a little bit above the container. Once box-shadow is added to this pseudo-element, the expected appearance will be achieved.

    Note: In the below snippet, I've added a red colored shadow and also colored the top and bottom div just to illustrate how the shadow extend above and below the #content. I've also removed extra properties which are no longer required and shortened a few others.

    I would also strongly recommend converting the three div into one as it would make the entire thing a lot more simpler.

    body {
      margin-top: 30px;
    }
    div#content {
      position: relative;
      height: 100px;
      width: 240px;
      padding: 20px 30px 20px 30px;
      margin-right: auto;
      margin-left: auto;
      color: #515348;
      font-size: 76%;
      line-height: 1.6em;
      background: #FFF;
      border-left: 1px solid grey;
      border-right: 1px solid grey;
    }
    div#content:before {
      position: absolute;
      content: '';
      left: -1px;
      top: -7px;  /* positioning above makes shadow extend above */
      height: calc(100% + 14px);  /* to cover top and bottom */
      width: 100%;
      z-index: -1;  /* to send the elements and their shadow behind  */
      box-shadow: 6px 0px 12px -6px rgba(255, 0, 0, 0.75), -6px 0px 12px -6px rgba(255, 0, 0, 0.75);
    }
    #top {
      position: relative;
      height: 10px;
      width: 300px;
      margin: 0 auto;
      background: #0F0;
      border-radius: 8px 8px 0px 0px;
      border: 1px solid grey;
      border-width: 1px 1px 0px 1px;
    }
    #bot {
      position: relative;
      height: 10px;
      width: 300px;
      margin: 0 auto;
      background: #00F;
      border-radius: 0px 0px 8px 8px;
      border: 1px solid grey;
      border-width: 0px 1px 1px 1px;
    }
    <div id="top"></div>
    <div id="content"></div>
    <div id="bot"></div>