85

I'm wondering about the support for side specific inner shadows in css3.

I know this works great on supported browsers.

div { box-shadow:inset 0px 1px 5px black; }

I'm just curious as to whether there is a way to achieve something like:

div { box-shadow-top:inset 0px 1px 5px black; }
ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
ndmweb
  • 3,370
  • 6
  • 33
  • 37
  • Possible duplicate of [How to get box-shadow on left & right sides only](http://stackoverflow.com/questions/11997032/how-to-get-box-shadow-on-left-right-sides-only), which has more detailed answers and explanations. – brichins Mar 21 '17 at 17:21

11 Answers11

156

This is what worked for me:

box-shadow: inset 1px 4px 9px -6px;

Example: http://jsfiddle.net/23Egu/

bryanbraun
  • 3,025
  • 2
  • 26
  • 38
nischtname
  • 2,193
  • 1
  • 23
  • 21
  • Awesome! I have struggled around with this forever, but this single line brings the most sexy one side border ever. Thanks, man! – Sliq Oct 28 '12 at 19:28
  • 12
    Worth noting that you can switch that to `box-shadow: inset 1px -4px 9px -6px;` for a bottom shadow. – Justin Russell Jun 26 '13 at 15:16
  • 7
    Left side shadow: `box-shadow: inset 4px 1px 9px -6px;` Right side shadow: `box-shadow: inset -4px 1px 9px -6px;` – bryanbraun Feb 24 '14 at 01:08
  • hmm so all we are doing is that we are using big spread value and then negating it using negative blur. Clever – Samiullah Khan Feb 14 '18 at 08:34
11

I don't think your really need box-shadow-top because if you set offsetx to 0 and offsety to any positive value only remaining shadow is on top.

if you want to have shadow on top and shadow in the bottom you just can simply use two divs:

<div style="box-shadow:inset 0 1px 5px black;">
  <div style="box-shadow:inset 0 -1px 5px black;">
    some content
  </div>
</div>

if you want to get rid of shadow on sides use rgba instead of hex color and set bigger offsety:

box-shadow:inset 0 5px 5px rgba(0,0,0,.5) 

this way you give shadow more opacity so sides stay hidden and with more offset you get less opacity

full example:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <style type="text/css">
            body {
                background: #1C1C1C;
            }
            div {
                margin: 50px auto;
                width: 200px;
                height: 200px;
                background: #fff;
                -webkit-border-radius: 20px;
                -khtml-border-radiust: 20px;
                -moz-border-radius: 20px;
                -o-border-radius: 20px;
                border-radius: 20px;
                box-shadow:inset 0px 5px 5px rgba(0,0,0,.5); 
            }
            div > div {
                background:none;
                box-shadow:inset 0px -5px 5px rgba(0,0,0,.5); 
            }
        </style>
    </head>
    <body>
        <div><div></div></div>
    </body>
</html>
seler
  • 8,803
  • 4
  • 41
  • 54
  • And the shadow will be more spread than you might want. And the sides have shifted as well. Its definitely a different result than `box-shadow-top` would give. **edit** But that's how I usually do it too =) – Rudie May 06 '11 at 22:17
  • @Rudie, if you want to get rid of shadow on sides use `rgba` instead of `hex` color and set bigger `offsety`: box-shadow: 0 5px 5px rgba(0,0,0,.5) this way you give shadow more opacity so sides stay hidden and with more offset you get less opacity – seler May 06 '11 at 22:36
  • 3
    FYI, instead of having two nested div's to achieve a top and bottom shadows at the same time you can do it with one div using this: `box-shadow:inset 0 1px 5px black, inset 0 -1px 5px black;` – Jake Wilson Aug 04 '11 at 05:09
10

using :before and after elements with regular shadows cut of by overflow:hidden on the parent box like in this example: http://dabblet.com/gist/2585782

CSS

/**
 * Top and Bottom inset shadow
 */


#element{
  background-color: #E3F2F7;
  height: 55px;
  position: relative; /* to position pseudo absolute*/
  overflow: hidden; /* to cut of overflow shadow*/
  margin-top: 200px;    
}

#element:before , #element:after{
  content: "\0020";
  display: block;
  position: absolute;
  width: 100%;
  height: 1px; /* when 0 no shadow is displayed*/
  box-shadow: #696c5c 0 0 8px 0;
}

#element:before { top: -1px} /* because of height: 1*/
#element:after { bottom: -1px}  /* because of height: 1*/

HTML

<div id="element"></div>
Zuul
  • 16,217
  • 6
  • 61
  • 88
Jakob Cosoroaba
  • 1,702
  • 4
  • 24
  • 34
  • This is the technique that worked for me. In my case, #element was scrollable, so I had to change position to sticky for it to work. – Mihai Răducanu Apr 15 '20 at 09:14
5

You can use a background gradient for a work around in most cases:

SCSS(with compass) example:

@include background(linear-gradient(top, #666 1%, #999 3%, #ddd 6%, #f6f6f6 9%, #f6f6f6 92%, #ddd 94%, #999 97%, #666 99%) );
Omar Jalalzada
  • 1,143
  • 1
  • 9
  • 7
  • 1
    Sometimes we need to just step back and think about what we're trying to accomplish. And this is *often* what we're after with an one-sided inner box shadow. Brilliant. I'd upvote twice if I could! – random_user_name Nov 02 '13 at 20:47
  • When I first saw this comment, I thought it looked way to complicated to ever work, but it worked perfectly. Thank you!! – Alex Jul 09 '16 at 19:39
4
box-shadow: inset 5px 0 5px -5px rgba(0,0,0,0.5),inset -5px 0 5px -5px rgba(0,0,0,0.5);
-moz-box-shadow: inset 5px 0 5px -5px rgba(0,0,0,0.5),inset -5px 0 5px -5px rgba(0,0,0,0.5);
-webkit-box-shadow: inset 5px 0 5px -5px rgba(0,0,0,0.5),inset -5px 0 5px -5px rgba(0,0,0,0.5);
-o-box-shadow: inset 5px 0 5px -5px rgba(0,0,0,0.5),inset -5px 0 5px -5px rgba(0,0,0,0.5);

This works just lovely :)

Here is a codepen illustrating it: http://codepen.io/poopsplat/pen/cGBLy

3

For the same shadow but only on the top :

box-shadow: inset 0px 6px 5px -5px black;

To have the shadow in one direction you have to negate the "blur" parameter with the "spread" parameter and then adjust the "h-pos" and/or "v-pos" parameters by this same value. It doesn't work with opposite border or triple border. You have to add one more definition.

More examples here : http://codepen.io/GBMan/pen/rVXgqP

GBMan
  • 475
  • 2
  • 4
  • 16
1

I just had this problem myself. The solution that I found was with multiple box-shadows (one for each side that you want your shadow). Here is the definition:

box-shadow: none|h-offset v-offset blur spread color |inset|initial|inherit;

Here is how to think it:

  • first, make the spread 0 (this will disable the effect on all sides)
  • the h-offset (if you set it to be positive, it will cast on the left side, if you set it negative, on the right side)
  • the v-offset (if you set it to be positive, it will cast on the top side, if you set it negative, on the bottom side

Here you can see my case with box-shadow on three sides (left, top, right and the bottom is with same color as the background to create the effect that I wanted - the left side and the right go all the way to the bottom) https://codepen.io/cponofrei/pen/eMMyQX

1

No, not directly, but you can crop off the parts that you don't want by putting it in a div with overflow: hidden:

http://jsfiddle.net/Vehdg/

0

You can accomplish a single-sided, inner shadow by setting your div to overflow:hidden and adding shadow elements along the borders.

Set an inner shadow on the top and bottom borders of a division:

HTML

&ltdiv id="innerShadow">
    &ltdiv id="innerShadowTop">
        Content...
    &ltdiv id="innerShadowBottom">
&lt/div>

CSS

#innerShadow
{
    position: relative;
    overflow: hidden;
}

#innerShadowTop
{
    width: 100%;
    height: 1px;
    margin: 0;
    padding: 0;
    position: absolute;
    top: -1px;
    -moz-box-shadow: 0px 1px 6px 1px rgba(0, 0, 0, 0.65);
    -webkit-box-shadow: 0px 1px 6px 1px rgba(0, 0, 0, 0.65);
    -o-box-shadow: 0px 1px 6px 1px rgba(0, 0, 0, 0.65);
    box-shadow: 0px 1px 6px 1px rgba(0, 0, 0, 0.65);
}

#bannerShadowBottom
{
    width: 100%;
    height: 1px;
    margin: 0;
    padding: 0;
    position: absolute;
    bottom: -1px;
    -moz-box-shadow: 0px -1px 6px 1px rgba(0, 0, 0, 0.65);
    -webkit-box-shadow: 0px -1px 6px 1px rgba(0, 0, 0, 0.65);
    -o-box-shadow: 0px -1px 6px 1px rgba(0, 0, 0, 0.65);
    box-shadow: 0px -1px 6px 1px rgba(0, 0, 0, 0.65);
}
Jason George
  • 6,992
  • 8
  • 44
  • 60
  • Many would argue that adding extra markup like this is not semantic and is bad practice. This could be achieved by using `inset` and getting creative using the values of the box-shadow css. Remember that you can stack box-shadows on the same element. So one could use something like @Jakobud said in an above comment: `box-shadow:inset 0 1px 5px black, inset 0 -1px 5px black;` Another way,, that is only slightly less offensive than adding unnecessary markup, is to use `:before` and `:after` selectors. But why do that if you can do it by directly selecting and styling the original element. – ORyan Apr 23 '13 at 23:54
0

Multiple box shadows did the trick for me.

box-shadow:
        inset 0 -8px 4px 4px rgb(255,255,255),
        inset 0 2px 4px 0px rgba(50, 50, 50, 0.75);

http://jsfiddle.net/kk66f/

shaunw
  • 354
  • 3
  • 11
0

box-shadow is for all four sides. You can't change that (yet?). The 4 sizes in the box-shadow definition are OffsetX, offsetY, Blur and Spread.

Rudie
  • 52,220
  • 42
  • 131
  • 173
  • 1
    Spread and Blur are not the same. There are separate values for each. So technically there are 6. `Inset/Outset`, `OffsetX`, `OffsetY`, `BlurRadius`, `SpreadRadius` and `Color`. As others have pointed out, you can specify one side like this `box-shadow: inset 0 8px 6px -6px black;` – ORyan Apr 23 '13 at 23:46
  • 1
    True. I've changed the answer to reflect all 4 **sizes**. – Rudie Apr 24 '13 at 11:13