248

Any way to get box-shadow on left & right (horizontal?) sides only with no hacks or images. I am using:

box-shadow: 0 0 15px 5px rgba(31, 73, 125, 0.8);

But it gives shadow all around.

I have no borders around the elements.

Jawad
  • 8,352
  • 10
  • 40
  • 45

16 Answers16

293

NOTE: I suggest checking out @Hamish's answer below; it doesn't involve the imperfect "masking" in the solution described here.


You can get close with multiple box-shadows; one for each side

box-shadow: 12px 0 15px -4px rgba(31, 73, 125, 0.8), -12px 0 8px -4px rgba(31, 73, 125, 0.8);

http://jsfiddle.net/YJDdp/

Edit

Add 2 more box-shadows for the top and bottom up front to mask out the that bleeds through.

box-shadow: 0 9px 0px 0px white, 0 -9px 0px 0px white, 12px 0 15px -4px rgba(31, 73, 125, 0.8), -12px 0 15px -4px rgba(31, 73, 125, 0.8);

http://jsfiddle.net/LE6Lz/

Community
  • 1
  • 1
deefour
  • 34,974
  • 7
  • 97
  • 90
  • 1
    Ok. Thanks. There is a little bit of shdow on top & bottom as well possibly due to the blur/radius but I guess have to live with it. – Jawad Aug 17 '12 at 00:00
  • 5
    -1: the shadow doesn't get to the corners, they end a few pixels before. – Francisco Corrales Morales Aug 12 '14 at 22:18
  • 4
    I can't believe this solution is so highly rated. It expands the object towards top and bottom (by applying solid shadow) so it is only useful when the div is on a uniform background and can have space above and below it. Very limit and tied to context solution indeed. Hamish's solution is way superior and simpler. – Ejaz Sep 06 '14 at 00:49
  • There is a better solution (2020). Look at Luke's answer below: https://stackoverflow.com/a/62367058/760777 – RWC Jun 22 '20 at 01:55
204

I wasn't satisfied with the rounded top and bottom to the shadow present in Deefour's solution so created my own.

inset box-shadow creates a nice uniform shadow with the top and bottom cut off.

To use this effect on the sides of your element, create two pseudo elements :before and :after positioned absolutely on the sides of the original element.

div:before, div:after {
  content: " ";
  height: 100%;
  position: absolute;
  top: 0;
  width: 15px;
}
div:before {
  box-shadow: -15px 0 15px -15px inset;
  left: -15px;
}
div:after {
  box-shadow: 15px 0 15px -15px inset;
  right: -15px;
}

div {
  background: #EEEEEE;
  height: 100px;
  margin: 0 50px;
  width: 100px;
  position: relative;
}
<div></div>

Edit

Depending on your design, you may be able to use clip-path, as shown in @Luke's answer. However, note that in many cases this still results in the shadow tapering off at the top and bottom. This taper is subtle and depending on your colour scheme and blur radius you may find it acceptable. In this example I have added a 2nd box to make the taper easy to see:

div {
  width: 100px;
  height: 50px;
  background: #EEE;
  box-shadow: 0 0 15px 0px #000;
  clip-path: inset(0px -15px 0px -15px);
  position: relative;
  margin: 0 50px;
}
<div>1</div>
<div>2</div>
Hamish
  • 2,763
  • 1
  • 17
  • 21
  • 11
    Very clever. Note your `:after` needs a `top: 0` also. – Sprintstar Oct 09 '13 at 11:07
  • 1
    I had to add `display: inline-block` to pseudo classes for your example to work. All in all: nice solution. +1 – Morpheus Mar 06 '14 at 14:46
  • 2
    I think this should have been the accepted answer. Because the one by @Deefour work good by that leaves the top and bottom corners on the sides blank. On other hand, this particuar solution is just perfect. – Rishabh Shah Jun 21 '14 at 05:07
  • For some elements it's necessary to use `top: 0;`, `bottom: 0;`, and `display: block;` to achieve the full height, rather than `height: 100%;`. – Pete May 28 '15 at 21:07
  • Alas, this won't work for elements on which you have `overflow: auto`. – Frerich Raabe Nov 11 '19 at 14:35
  • @FrerichRaabe If you are able to add a wrapping element inside the outer div, then you can apply your overflow rule to that: http://jsfiddle.net/mkgqb9z2/1/ – Hamish Nov 11 '19 at 15:39
  • 1
    @Hamish Yeah, that's what I did for now :-) Pity, one appealing feature of this approach is that it (usually) does `not` requre any helper `
    ` elements. :-)
    – Frerich Raabe Nov 11 '19 at 16:15
  • 2
    There is a better solution (2020). Look at Luke's answer below: https://stackoverflow.com/a/62367058/760777 – RWC Jun 22 '20 at 01:56
32

Negative spread and Masking shadow

CSS box-shadow uses 4 parameters: h-shadow, v-shadow, blur, spread:

box-shadow: 10px 0 8px -8px black;

The blur parameter adds the gradient effect, but adds also a little shadow on top and bottom borders. To get rid of this side effect we can use:

  • Negative spread reduces the shadow on all borders: you can play with it trying to remove that little vertical shadow without affecting too much the one obn the sides (it's easier for small shadows, 5 to 10px.)

  • Masking shadows of the same color of the background (white in this case), which allows for ticker shadows. Note that this masking shadow needs to have blur = 0 to fully cover the side effects.

Here two examples, the second one uses Masking shadow:

div{
    width: 100px;
    height: 100px;
    border: 1px solid green;
    margin: 10px;
    float: left;
}
#example1{
    box-shadow: -10px 0 8px -8px black, 10px 0 8px -8px black;
}
#example2{
    box-shadow: 
        0 -6px white,
        0 6px white, 
        -7px 0 4px -3px black, 
        7px 0 4px -3px black;
}
<div id="example1"></div>
<div id="example2"></div>

If none of these approaches suit your needs, you can also add an absolute div on the side of any existing divs.

Just remember to set the container div as position: relative so this absolute div will stay inside.

#example3 {
  position: relative;
  width: 100px;
  height: 100px;
  margin: 10px;
  border: 1px solid green;
}

.shadow {
  position: absolute;
  height: 100%;
  width: 4px;
  left: 0px;
  top: 0px;
  box-shadow: -4px 0 3px black;
}
<div id="example3">
  content here
  <div class="shadow"></div>
</div>
T30
  • 11,422
  • 7
  • 53
  • 57
29

Try this, it's working for me:

    box-shadow: -5px 0 5px -5px #333, 5px 0 5px -5px #333;
krishna kinnera
  • 1,543
  • 12
  • 10
22

clip-path is now (2020) the best way I have found to achieve box-shadows on specific sides of elements, especially when the required effect is a "clean cut" shadow at particular edges, like this:

.shadow-element {
    width: 100px;
    height: 100px;
    background-color: #FFC300;
    box-shadow: 0 0 10px 5px rgba(0,0,0,0.75);
    clip-path: inset(0px -15px 0px -15px);

    /* position and left properties required to bring element out from edge of parent
    so that shadow can be seen; margin-left would also achieve the same thing */
    position: relative;
    left: 15px;
}
<div class="shadow-element"></div>

...as opposed to an attenuated/reduced/thinning shadow like this:

.shadow-element {
    width: 100px;
    height: 100px;
    background-color: #FFC300;
    box-shadow: 15px 0 15px -10px rgba(0,0,0,0.75), -15px 0 15px -10px rgba(0,0,0,0.75);

    /* position and left properties required to bring element out from edge of parent
    so that shadow can be seen; margin-left would also achieve the same thing */
    position: relative;
    left: 15px;
}
<div class="shadow-element"></div>

Simply apply the following CSS to the element in question:

box-shadow: 0 0 Xpx Ypx [hex/rgba]; /* note 0 offset values */
clip-path: inset(Apx Bpx Cpx Dpx);

Where:

  • Apx sets the shadow visibility for the top edge
  • Bpx right
  • Cpx bottom
  • Dpx left

Enter a value of 0 for any edges where the shadow should be hidden and a negative value (the same as the combined result of the blur radius + spread values - Xpx + Ypx) to any edges where the shadow should be displayed.

Luke
  • 4,825
  • 2
  • 30
  • 37
  • 1
    This is the best answer. It's even simpler. You can just apply the shadow directly to your image. Works like a charm. Example: **img.shadowed { box-shadow: 0 0 15px rgba(0,0,0,0.75); clip-path: inset(0px -15px 0px -15px); }** – RWC Jun 22 '20 at 01:52
  • Even in your example you can see the top and bottom corners of the shadow curving in. Still, may be good for some use cases. – Hamish Jun 23 '20 at 15:35
  • @Hamish, are you looking at the `clip-path` example? There are 2 code snippets. The first uses `clip-path` and has a completely clean cut off with no "top and bottom corners curving in" - very much like your solution (but with much less CSS required). The second code-snippet is an example simply for comparison - many solutions result in a dispersing box-shadow which is often not what people are wanting to achieve. – Luke Jun 23 '20 at 21:29
  • If you're wanting a stronger shadow you can simply alter the `box-shadow` property to something like `0 0 10px 5px rgba(0,0,0,0.75);`. Note the added `spread` value and reduced `blur-radius`. – Luke Jun 23 '20 at 21:38
  • @Hamish I've updated my first snippet to demonstrate. – Luke Jun 23 '20 at 21:55
  • @Luke Yes I'm looking at the clip-path example. It's subtle but the top and bottom of the shadow curve in because the radial gradient at the corners of the shadow start before the edge of the element. The effect is especially visible for low spread values. The clip-path solution is great for cases where spread >= blur because the rounded corner of the shadow is pushed outside the clipped area. – Hamish Jun 24 '20 at 13:13
5

Another way is with overflow-y:hidden on the parent with padding:

body {
    padding: 30px;
}
#wrap {
    overflow-y: hidden;
    padding: 0 10px;
}
#wrap > div {
    width: 100px;
    height: 100px;
    box-shadow: 0 0 20px -5px red;
}
<div id="wrap">
    <div></div>
</div>
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
John Magnolia
  • 16,769
  • 36
  • 159
  • 270
4

You must use the multiple box-shadow; . inset property makes it look nice and inside:

div {
    box-shadow: inset 0 12px  15px -4px rgba(31, 73, 125, 0.8), inset 0 -12px  8px -4px rgba(31, 73, 125, 0.8);
    width: 100px;
    height: 100px;
    margin: 50px;
    background: white;
}
<div></div>
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Ashisha Nautiyal
  • 1,389
  • 2
  • 19
  • 39
3

This works fine for all browsers:

-webkit-box-shadow: -7px 0px 10px 0px #000, 7px 0px 10px 0px #000;
-moz-box-shadow: -7px 0px 10px 0px #000, 7px 0px 10px 0px #000;
box-shadow: -7px 0px 10px 0px #000, 7px 0px 10px 0px #000;
Jibber
  • 39
  • 1
  • 4
    this does not work even a little bit. Maybe the format changed but this says to move the shadow 7 pixels left, 0 pixels down, blur the outer 10 pixels and extend the blur 0 pixels. Breaking it down: a 17 pixel blur on the left, a 10 pixel blur on top and bottom and a 3 pixel blur on the right. Which is what I get. – john k Dec 09 '13 at 04:27
2

For a nice inset shadow in right and left sides on images, or any other content, use it this way (the z-index:-1 does a nice trick when showing images or inner objects with insets):

.shadowcontainer{
    display:inline-flex;
    box-shadow: inset -40px 0px 30px -30px rgba(0,0,0,0.9),inset 40px 0px 30px -30px rgba(0,0,0,0.9);
}

.innercontent{
    z-index:-1
}
<div class="shadowcontainer">
<img src="https://www.google.es/images/srpr/logo11w.png" class="innercontent" style="with:100%"/>
</div>
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
0

In some situations you can hide the shadow by another container. Eg, if there is a DIV above and below the DIV with the shadow, you can use position: relative; z-index: 1; on the surrounding DIVs.

NateS
  • 5,751
  • 4
  • 49
  • 59
0

For horizontal only, you can trick the box-shadow using overflow on its parent div:

.parent{
    overflow:hidden;
}
.box-shadow{
    box-shadow: box-shadow: 0 5px 5px 0 #000;
}
<div class="parent">
    <div class="box-shadow">content</div>
</div>
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
0

Another idea could be creating a dark blurred pseudo element eventually with transparency to imitate shadow. Make it with slightly less height and more width i.g.

Garavani
  • 755
  • 1
  • 13
  • 28
0

You can use 1 div inside that to "erase" the shadow:

.yourdiv{
    position:relative;
    width:400px;
    height:400px;
    left:10px;
    top:40px;
    background-color:white;
    box-shadow: 0px 0px 1px 0.5px #5F5F5F;

}
.erase{
    position:absolute;
    width:100%;
    top:50%;
    height:105%;
    transform:translate(0%,-50%);
    background-color:white;
}

You can play with "height:%;" and "width:%;" to erase what shadow you want.

0

This worked for me:

box-shadow: 0 5px 5px 0 #000;
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Nitika Chopra
  • 1,281
  • 17
  • 22
0

I tried to copy the bootstrap shadow-sm just in the right side, here is my code:

.shadow-rs{
    box-shadow: 5px 0 5px -4px rgba(237, 241, 235, 0.8);
}
OAH
  • 1,160
  • 2
  • 11
  • 24
0

If you want your div to have an arrow on top of it, use this:

box-shadow: -1px -1px 1px rgba(0, 0, 0, 0.1);
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61