如何在元素的一侧创建阴影效果?

280

有没有一种方法只在底部放置阴影?我有一个菜单,旁边有2个图片。我不想要右侧的阴影,因为它会重叠到右侧的图片上。我不喜欢使用图片来实现这个效果,那么有没有一种类似于 box-shadow-bottom: 10px #FFF; 的方式只在底部放置阴影?

-moz-box-shadow: 0px 3px 3px #000;
-webkit-box-shadow: 0px 3px 3px #000;
box-shadow-bottom: 5px #000;
/* For IE 8 */
-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=180, Color='#000000')";
/* For IE 5.5 - 7 */
filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=180, Color='#000000');

10
你所接受的答案提到了box-shadow-bottom,但这个属性并不存在,并且也没有被任何人支持。请参见http://nicolasgallagher.com/css-drop-shadows-without-images/demo/以获取合法的投影技术。 - Paul Irish
@Paul...我打错字了,已经修复了。 - Hristo
1
你CSS示例中的注释是误导性的——filter在IE8和IE9中也可以工作。在这种情况下不需要使用-ms-filter - Mathias Bynens
你可以使用这个现实的插入CSS阴影:https://dev59.com/9GIj5IYBdhLWcg3wIx3W#20596554 - Armel Larcier
18个回答

271

更新4

与第三次更新相同,但使用现代的css (=更少的规则),因此不需要在伪元素上进行特殊定位。


(Original Answer: "最初的回答")

#box {
    background-color: #3D6AA2;
    width: 160px;
    height: 90px;
    position: absolute;
    top: calc(10% - 10px);
    left: calc(50% - 80px);
}

.box-shadow:after {
    content:"";
    position:absolute;
    width:100%;
    bottom:1px;
    z-index:-1;
    transform:scale(.9);
    box-shadow: 0px 0px 8px 2px #000000;
}
<div id="box" class="box-shadow"></div>

更新3

我之前的回答都使用了额外的标记来创建这个效果,其实并不一定需要。我认为这是一个更加简洁的解决方案...唯一的诀窍就是通过调整值来获得阴影的正确位置以及阴影的强度/不透明度。这里有一个新的fiddle,使用伪元素

http://jsfiddle.net/UnsungHero97/ARRRZ/2/

HTML

<div id="box" class="box-shadow"></div>

CSS

#box {
    background-color: #3D6AA2;
    width: 160px;
    height: 90px;
    margin-top: -45px;
    margin-left: -80px;
    position: absolute;
    top: 50%;
    left: 50%;
}

.box-shadow:after {
    content: "";
    width: 150px;
    height: 1px;
    margin-top: 88px;
    margin-left: -75px;
    display: block;
    position: absolute;
    left: 50%;
    z-index: -1;
    -webkit-box-shadow: 0px 0px 8px 2px #000000;
       -moz-box-shadow: 0px 0px 8px 2px #000000;
            box-shadow: 0px 0px 8px 2px #000000;
}

更新2

显然,你可以通过在box-shadow CSS中添加一个额外的参数来实现这个,正如其他人所指出的。下面是演示:

http://jsfiddle.net/K88H9/821/

CSS

-webkit-box-shadow: 0 4px 4px -2px #000000;
   -moz-box-shadow: 0 4px 4px -2px #000000;
        box-shadow: 0 4px 4px -2px #000000;

这将是一个更好的解决方案。添加的额外参数描述如下:

第四个长度是扩展距离。正值会导致阴影形状在指定半径内向所有方向扩展,负值会导致阴影形状收缩。

更新

请查看jsFiddle上的演示:http://jsfiddle.net/K88H9/4/

我的方法是创建一个"阴影元素",该元素会隐藏在您想要有阴影的实际元素后面。我使阴影元素的宽度比实际元素窄2倍你指定的阴影宽度,然后适当地对齐它。

HTML


最初的回答未提供。
<div id="wrapper">
    <div id="element"></div>
    <div id="shadow"></div>
</div>

CSS

#wrapper {
    width: 84px;
    position: relative;
}
#element {
    background-color: #3D668F;
    height: 54px;
    width: 100%;
    position: relative;
    z-index: 10;
}
#shadow {
    background-color: #3D668F;
    height: 8px;
    width: 80px;
    margin-left: -40px;
    position: absolute;
    bottom: 0px;
    left: 50%;
    z-index: 5;
    -webkit-box-shadow: 0px 2px 4px #000000;
       -moz-box-shadow: 0px 2px 4px #000000;
            box-shadow: 0px 2px 4px #000000;
}

最初的回答

是的,您可以使用提供的相同语法来实现此操作。第一个值控制水平定位,第二个值控制垂直定位。因此,请按如下方式将第一个值设置为0px,将第二个值设置为所需的任意偏移量:

-webkit-box-shadow: 0px 5px #000000;
   -moz-box-shadow: 0px 5px #000000;
        box-shadow: 0px 5px #000000;

更多关于盒子阴影的信息,请查看以下链接: 注意:本文保留了HTML标签。

2
您不一定需要添加一个空的div来实现模糊阴影。声明中的第三个值:box-shadow: 0 2px 4px #000000 是一个模糊值。请参见此处[http://jsfiddle.net/K88H9/7/]。但是您会注意到,在元素的左右两侧有一点模糊,而在Hristo的解决方案中则没有。 - user641656
9
没有"box-shadow-bottom"属性,这个效果绝对不需要额外的元素。呸。 - Lea Verou
7
“box-shadow-bottom”虽然很有创意,但实际上并不存在。 - miketaylr
3
冷静点,人们...这只是一个该死的打字错误。 - Hristo
1
@gryzzly...我已经编辑了我的答案,直到大家指出我的打字错误之前我都没看到。对此很抱歉。 - Hristo
显示剩余11条评论

82

使用扩展参数来使阴影变小:

.shadow {
  -webkit-box-shadow: 0 6px 4px -4px black;
  -moz-box-shadow: 0 6px 4px -4px black;
  box-shadow: 0 6px 4px -4px black;
}
<div class="shadow">Some content</div>

Live demo: http://dabblet.com/gist/a8f8ba527f5cff607327

阴影不出现在边缘,需要使扩散半径 (第四个参数) 的绝对值等于模糊半径 (第三个参数)。


1
这并不实际有效。乍一看似乎阴影只在底部,但实际上它仍然会超出边缘。每个人的例子都是用相当深的蓝色框...把框变成白色,你就会看到整个阴影了。 - MilkyTech
@Chris M:只需增加spread参数:尝试使用box-shadow:0 8px 4px -6px的示例,您将只看到底部阴影! - T30
2
再次将盒子变为白色,就像这个fiddle中的一样,你仍然会看到阴影一直延伸到侧面,而且现在它没有完全覆盖底部。你愿意在扩展参数上走多远来摆脱侧面?此外,最好让151声望的人不要编辑7k声望的人的答案。请在评论中留下它。 - MilkyTech
1
@T30 当然,通过进一步减小 spread 参数,你最终可以摆脱阴影的边缘。但此时你的阴影宽度与盒子的宽度相差甚远。你的盒子宽度为84像素,而阴影宽度只有72像素。 - MilkyTech
1
更新的答案。但基本上,除了减少扩散半径和调整Y偏移量之外,没有太多可以做的了。也许可以使用渐变代替阴影?此外,我不介意别人编辑我的帖子,但我不欣赏别人在我的帖子中添加一些类似Engrish的语句。我也不是母语为英语的人,我理解其中的挑战,但如果我正在编辑别人的帖子,我会感到足够的责任心,至少要仔细检查我所添加的内容是否有点意义,语法是否尴尬错误。 - Lea Verou
显示剩余2条评论

33

您还可以使用clip-path来剪切(隐藏)除了您想要显示的边缘之外的所有溢出边缘:

.shadow {
  box-shadow: 0 4px 4px black;
  clip-path: polygon(0 0, 100% 0, 100% 200%, 0 200%);
}

请查看clip-path (MDN)。使用 polygon 的参数是左上角点、右上角点、右下角点和左下角点。通过将底部边缘设置为200%(或其他大于100%的数字),可以将溢出限制在底部边缘。

示例:

使用 clip-path 分离具有顶部、右侧、底部和左侧 box-shadow 的方块的示例

.shadow {
  box-shadow: 0 0 8px 5px rgba(200, 0, 0, 0.5);
}
.shadow-top {
  clip-path: polygon(0% -20%, 100% -20%, 100% 100%, 0% 100%);
}
.shadow-right {
  clip-path: polygon(0% 0%, 120% 0%, 120% 100%, 0% 100%);
}
.shadow-bottom {
  clip-path: polygon(0% 0%, 100% 0%, 100% 120%, 0% 120%);
}
.shadow-left {
  clip-path: polygon(-20% 0%, 100% 0%, 100% 100%, -20% 100%);
}

.shadow-bottom-right {
  clip-path: polygon(0% 0%, 120% 0%, 120% 120%, 0% 120%);
}

/* layout for example */
.box {
  display: inline-block;
  vertical-align: top;
  background: #338484;
  color: #fff;
  width: 4em;
  height: 2em;
  margin: 1em;
  padding: 1em;
}
<div class="box">none</div>
<div class="box shadow shadow-all">all</div>
<div class="box shadow shadow-top">top</div>
<div class="box shadow shadow-right">right</div>
<div class="box shadow shadow-bottom">bottom</div>
<div class="box shadow shadow-left">left</div>
<div class="box shadow shadow-bottom-right">bottom right</div>


2
所以,简单来说,clip-path是overflow: hidden属性的强化版。这很干净。;) - Stark
这个答案的扩展可以在这里找到:https://dev59.com/s2035IYBdhLWcg3wYO11#65807809 - Temani Afif

33

如果您在背景上有一个固定的颜色,可以通过使用两个遮罩阴影并将它们的颜色设置为背景的颜色,模糊值为0来隐藏侧边阴影效果,例如:

box-shadow: 
    -6px 0 white,         /*Left masking shadow*/
    6px 0 white,          /*Right masking shadow*/
    0 7px 4px -3px black; /*The real (slim) shadow*/

注意,黑色阴影必须是最后一个,并且具有负扩展(-3px),以防止它延伸到角落之外。

这里是fiddle(更改遮罩阴影的颜色,以查看它实际上是如何工作的)。

div{
    width: 100px;
    height: 100px;
    border: 1px solid pink;
    box-shadow: -6px 0 white, 6px 0 white, 0 7px 5px -2px black;
}
<div></div>

enter image description here


1
使用“透明”颜色来遮盖阴影会更好,不是吗? - Redmega
@AngelJosephPiscola:聪明的提示.. 在答案中实现,谢谢! - T30
@T30 很棒,但请注意,使用透明遮罩时,您不需要固定颜色的背景 ;) - Redmega
我进行了更好的测试,发现透明阴影无法正常工作(http://jsfiddle.net/ac6nLxuz/),因此我撤销了最后的编辑。 - T30
看看engineear的回答:在大多数情况下,一个更好的(而且非常干净的)解决方案,参见stackoverflow.com/a/56654875/760777。 - undefined

7
我想这就是你需要的内容吧?

.shadow {
  -webkit-box-shadow: 0 0 0 4px white, 0 6px 4px black;
  -moz-box-shadow: 0 0 0 4px white, 0 6px 4px black;
  box-shadow: 0 0 0 4px white, 0 6px 4px black;
}
<div class="shadow">wefwefwef</div>


3
喜欢当别人不理解的时候。是的,他在玩弄第一个阴影(白色)的扩展,它将覆盖真正阴影(黑色)的边缘。这是获取完美单向阴影的唯一明智方法。当您需要在菜单的2个部分上具有相同的阴影时,特别有用。 - Zeno Popovici

5

另一个基于@theengineear的答案的想法,我将使用inset代替polygon。它更容易,因为它的工作方式与margin或padding相同。我还将依赖于CSS变量来轻松定义所有不同的情况。

.shadow {
  box-shadow: 0 0 8px 5px rgba(200, 0, 0, 0.5);
  clip-path:inset(var(--t,0) var(--r,0) var(--b,0) var(--l,0))
}

.top { --t:-100%; }
.right { --r:-100%;}
.bottom { --b:-100%; }
.left { --l:-100%;}


/* layout for example */

.box {
  display: inline-block;
  vertical-align: top;
  background: #338484;
  color: #fff;
  width: 4em;
  height: 2em;
  margin: 1em;
  padding: 1em;
}
<div class="box">none</div>
<div class="box shadow top right left bottom">all</div>
<div class="box shadow top">top</div>
<div class="box shadow right">right</div>
<div class="box shadow bottom">bottom</div>
<div class="box shadow left">left</div>
<div class="box shadow bottom right">bottom right</div>
<div class="box shadow bottom top">top bottom</div>
<div class="box shadow left top right">top left right</div>
<div class="box shadow left right"> left right</div>


3

阅读规范是更好的选择。没有box-shadow-bottom属性,正如Lea指出的那样,您应该始终将未加前缀的属性放在底部,在加前缀的属性之后。

所以正确的写法是:

.shadow {
  -webkit-box-shadow: 0px 2px 4px #000000;
  -moz-box-shadow: 0px 2px 4px #000000;
  box-shadow: 0px 2px 4px #000000;
}
<div class="shadow">Some content</div>


3
从两侧有阴影。 - shinzou

2

可以考虑使用一个包含 div,将其 overflow 属性设置为 hidden,并在底部添加一些填充。这似乎是最简单的解决方案。

很抱歉我自己没有想到这个方法,但在其他地方看到了

Using an element to wrap the element getting the box-shadow and a overflow: hidden on the wrapper you could make the extra box-shadow disappear and still have a usable border. This also fixes the problem where the element is smaller as it seems, because of the spread.

Like this:

#wrapper { padding-bottom: 10px; overflow: hidden; }
#elem { box-shadow: 0 0 10px black; }

Content goes here

Still a clever solution when it has to be done in pure CSS!

正如Jorgen Evens所说。


除了 padding-bottom(假设为5px)之外,您还可以设置负的 margin-bottom(-5px)来补偿添加的空间。 - fabio.sang

1
最好查阅阴影:

.header{
    -webkit-box-shadow: 0 -8px 73px 0 rgba(0,0,0,0.2);
    -moz-box-shadow: 0 -8px 73px 0 rgba(0,0,0,0.2);
    box-shadow: 0 -8px 73px 0 rgba(0,0,0,0.2);
}

这段代码目前正在使用于stackoverflow网站。


1

我也需要一个阴影,但只在图像下方设置,并稍微向左和向右。这对我有用:

.box-shadow {
   -webkit-box-shadow: 5px 35px 30px -25px #888888;
      -moz-box-shadow: 5px 35px 30px -25px #888888;
           box-shadow: 5px 35px 30px -25px #888888;
}

这个元素应用于整个页面的图片(980px x 300px)。
如果在调整设置时有帮助,它们的运行如下:
水平阴影、垂直阴影、模糊距离、扩展(即阴影大小)和颜色。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接