142

Is it possible to somehow only have inset box-shadow on one side of a div ? Note that I'm talking about an inset box-shadow here, not the normal outer box-shadow.

For example, in the following JSFiddle, you'll see that the inset shadow appears on all 4 sides, in varying degrees.

How do I get it to ONLY show at the top ? Or at most ONLY at top and bottom ?

JSFiddle: http://jsfiddle.net/ahmadka/KFrun/

.box {
  -webkit-box-shadow: inset 0px 5px 10px 1px #000000;
  box-shadow: inset 0px 5px 10px 1px #000000;
}

.text {
  padding: 20px;
}
<div class="box">
  <div class="text">
    Lorem ipsum ....
  </div>
</div>
leonheess
  • 16,068
  • 14
  • 77
  • 112
Ahmad
  • 12,886
  • 30
  • 93
  • 146
  • 3
    An alternate (and fully customizable) way would be a background gradient ... – vals Jul 10 '13 at 17:57
  • 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) – brichins Mar 21 '17 at 17:21

10 Answers10

309

This is what you are looking for. It has examples for each side you want with a shadow.

.top-box
{
    box-shadow: inset 0 7px 9px -7px rgba(0,0,0,0.4);
}
.left-box
{
    box-shadow: inset 7px 0 9px -7px rgba(0,0,0,0.4);
}
.right-box
{
    box-shadow: inset -7px 0 9px -7px rgba(0,0,0,0.4);
}
.bottom-box
{
    box-shadow: inset 0 -7px 9px -7px rgba(0,0,0,0.4);
}

See the snippet for more examples:

body {
    background-color:#0074D9;
}
div {
    background-color:#ffffff;
    padding:20px;
    margin-top:10px;
}
.top-box {
    box-shadow: inset 0 7px 9px -7px rgba(0,0,0,0.7);
}
.left-box {
    box-shadow: inset 7px 0 9px -7px rgba(0,0,0,0.7);
}
.right-box {
    box-shadow: inset -7px 0 9px -7px rgba(0,0,0,0.7);
}
.bottom-box {
    box-shadow: inset 0 -7px 9px -7px rgba(0,0,0,0.7);
}
.top-gradient-box {
    background: linear-gradient(to bottom, #999 0, #ffffff 7px, #ffffff 100%);
}
.left-gradient-box {
    background: linear-gradient(to right, #999 0, #ffffff 7px, #ffffff 100%);
}
.right-gradient-box {
    background: linear-gradient(to left, #999 0, #ffffff 7px, #ffffff 100%);
}
.bottom-gradient-box {
    background: linear-gradient(to top, #999 0, #ffffff 7px, #ffffff 100%);
}
<div class="top-box">
        This area has a top shadow using box-shadow
</div>

<div class="left-box">
        This area has a left shadow using box-shadow
</div>

<div class="right-box">
        This area has a right shadow using box-shadow
</div>

<div class="bottom-box">
        This area has a bottom shadow using box-shadow
</div>

<div class="top-gradient-box">
        This area has a top shadow using gradients
</div>
<div class="left-gradient-box">
        This area has a left shadow using gradients
</div>
<div class="right-gradient-box">
        This area has a right shadow using gradients
</div>
<div class="bottom-gradient-box">
        This area has a bottom shadow using gradients
</div>
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
Gordon Tucker
  • 6,653
  • 3
  • 27
  • 41
  • Good solution, however, it still causes the shadow to appear along other edges. Solution: make the spread radius (the param just before the colour) even smaller, lower, e.g. (the top-box): `box-shadow: inset 0 7px 9px -10px rgba(0,0,0,0.4);` – ellockie Nov 29 '22 at 03:06
  • @ellockie No, that actually decreases the shadow showing from the top too. – Muhammad Tanweer Jul 20 '23 at 12:31
14

The trick is a second .box-inner inside, which is larger in width than the original .box, and the box-shadow is applied to that.

Then, added more padding to the .text to make up for the added width.

This is how the logic looks:

box logic

And here's how it's done in CSS:

Use max width for .inner-box to not cause .box to get wider, and overflow to make sure the remaining is clipped:

.box {
    max-width: 100% !important;
    overflow: hidden;
}

110% is wider than the parent which is 100% in a child's context (should be the same when the parent .box has a fixed width, for example). Negative margins make up for the width and cause the element to be centered (instead of only the right part hiding):

.box-inner {
    width: 110%;
    margin-left:-5%;
    margin-right: -5%;
    -webkit-box-shadow: inset 0px 5px 10px 1px #000000;
    box-shadow: inset 0px 5px 10px 1px #000000;
}

And add some padding on the X axis to make up for the wider .inner-box:

.text {
    padding: 20px 40px;
}

Here's a working Fiddle.

If you inspect the Fiddle, you'll see:

.box .box-inner .text

casraf
  • 21,085
  • 9
  • 56
  • 91
13

Quite a bit late, but a duplicate answer that doesn't require altering the padding or adding extra divs can be found here: Have an issue with box-shadow Inset bottom only. It says, "Use a negative value for the fourth length which defines the spread distance. This is often overlooked, but supported by all major browsers"

From the answerer's fiddle:

box-shadow: inset 0 -10px 10px -10px #000000;
Community
  • 1
  • 1
drkario
  • 131
  • 1
  • 4
9

This comes a little close.

.box
{
    -webkit-box-shadow: inset -1px 10px 5px -3px #000000;
    box-shadow: inset -1px 10px 5px -3px #000000;
}
mohkhan
  • 11,925
  • 2
  • 24
  • 27
3

This might not be the exact thing you are looking for, but you can create a very similar effect by using rgba in combination with linear-gradient:

background: linear-gradient(rgba(0,0,0,.5) 0%, rgba(0,0,0,0) 30%);

This creates a linear-gradient from black with 50% opacity (rgba(0,0,0,.5)) to transparent (rgba(0,0,0,0)) which starts being competently transparent 30% from the top. You can play with those values to create your desired effect. You can have it on a different side by adding a deg-value (linear-gradient(90deg, rgba(0,0,0,.5) 0%, rgba(0,0,0,0) 30%)) or switching the colors around. If you want really complex shadows like different angles on different sides you could even start layering linear-gradient.

Here is a snippet to see it in action:

.box {
  background: linear-gradient(rgba(0,0,0,.5) 0%, rgba(0,0,0,0) 30%);
}

.text {
  padding: 20px;
}
<div class="box">
  <div class="text">
    Lorem ipsum ....
  </div>
</div>
leonheess
  • 16,068
  • 14
  • 77
  • 112
1

try it, maybe useful...

box-shadow: 0 0 0 3px rgb(255,255,255), 0 7px 3px #cbc9c9;
                    -webkit-box-shadow: 0 0 0 3px rgb(255,255,255), 0 7px 5px #cbc9c9;
                    -o-box-shadow: 0 0 0 3px rgb(255,255,255), 0 7px 5px #cbc9c9;
                    -moz-box-shadow: 0 0 0 3px rgb(255,255,255), 0 7px 5px #cbc9c9;  

above CSS cause you have a box shadow in bottom.
you can red more Here

Hamid Talebi
  • 1,298
  • 2
  • 24
  • 42
1

Setting all four at once is easy with the normal box-shadow. Setting 1 is easy using the negative spread, but you can do two or three sides easily enough (without adding divs) by leveraging pseudo elements like so:

.box-example {
    box-shadow: inset 0px 7px 9px -7px rgb(0 0 0 / 40%);
    height: 80px;
    border: 1px dashed grey;
    position: relative;
}
.box-example::after {
    content: " ";
    background-color: transparent;
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    box-shadow: inset 0px -7px 9px -7px rgb(0 0 0 / 40%);
}
.box-example2 {
    box-shadow: inset 0px 7px 9px -7px rgb(0 0 0 / 40%);
    height: 80px;
    border: 1px dashed grey;
    position: relative;
    margin-top: 8px;
}
.box-example2::before,
.box-example2::after {
    content: " ";
    background-color: transparent;
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    box-shadow: inset 0px -7px 9px -7px rgb(0 0 0 / 40%);
}
.box-example2::after {
    box-shadow: inset -7px 0px 9px -7px rgb(0 0 0 / 40%);
}
<div class="box-example">I have a top and bottom</div>
<div class="box-example2">I have a top, bottom, and right</div>
Joe
  • 308
  • 1
  • 7
0

Inset Box Shadow only on Top side?

#box {
            background: #CCC;
            -webkit-box-shadow: inset 0 20px 20px -20px rgba(0,0,0,0.8);
            -moz-box-shadow: inset 0 20px 20px -20px rgba(0,0,0,0.8);
            box-shadow: inset 0 20px 20px -20px rgba(0,0,0,0.8);
            font: bold 18px/1.2em sans-serif;
            height: auto;
            margin: 15px auto;
            padding: 75px 15px 25px;
            text-align: center;
            width: 80%;
        }
0

Literally you can't do such a thing, but you should try this CSS trick:

box-shadow: inset 0 3vw 6vw rgba(0,0,0,0.6), inset 0 -3vw 6vw rgba(0,0,0,0.6);
Dharman
  • 30,962
  • 25
  • 85
  • 135
0

This seems to be the simplest way:

box-shadow: inset 0 calc(7px + 42px) 0 -42px black;

Of course, you can omit the calc() part and set 49px instead; it's only there for clarity and/or DRY (e.g. by using custom vars).

The third [blur] field is set to zero to avoid confusion; feel free to put any value there.

Franc Jerez
  • 113
  • 3
  • 5