box-shadow是css中最基础的属性之一,都知道box-shadow可以生成阴影,那么它的生成阴影的过程是什么呢?以及如何用box-shadow制作不同的效果呢?相信你看完本文,会有自己的答案!
一、基本概念
首先看下MDN上的定义:
box-shadow 以由逗号分隔的列表来描述一个或多个阴影效果。该属性可以让几乎所有元素的边框产生阴影。如果元素同时设置了 border-radius ,阴影也会有圆角效果。多个阴影的z-ordering 和多个 text shadows 规则相同(第一个阴影在最上面)。
基本用法:
值的说明:
简单说明:
- inset关键字,可设可不设,inset代表阴影是向内的
- color,这个值可设可不设,但是因为用户代理不同,阴影的颜色的默认值也会不同,所以建议统一设置
- 可以给一个元素设置多个box-shadow,每一组用逗号“,”隔开,并且越靠前的优先级越高,会覆盖后面的阴影
二、从一个简答的例子开始,了解box-shadow的生成过程
html:
<div class="box">
<div>
css:
.box {
width: 300px;
height: 200px;
background-color: yellowgreen;
box-shadow: 30px 50px 20px #000;
}
- 首先在box元素的上层生成一个同box大小,形状完全相同的阴影,这里为矩形,颜色为#000
注意,此时阴影是在元素的上层
- 根据offset-x和offset-y,将阴影逐渐从上层移动出来,得到的结果就是,阴影向右移动30px,向下移动50px
- 这里我们设置了一个20px的模糊半径,此时就会以四个方向,每个方向的阴影边缘线为中心,左右扩展10px的区域,共20px,共同组成这个阴影区域,如下图:
这里只用右侧举例,从阴影边缘开始,左右各一半高斯模糊,共同组成模糊的半径,那么四个方向都会产生模糊效果
- 现在只剩下最后一步,就是将阴影与元素重叠的区域全部裁剪掉,如下图虚线内容
裁剪后就是我们最终的结果:
这里唯一需要注意的是,阴影本质是在元素上方的,并且最终被裁剪掉,而不是出现在元素的下方,所以从这点来说,是不同于text-shadow的,因为text-shadow是出现在元素下方的,并且不会有裁剪的过程,证明起来也很简单,分别给元素和字体设置透明就好了。 div设置透明颜色 很明显下面什么也没有
三、进一步了解参数
offset
这个属性比较简单,只用考虑是否为inset就行了
-
非inset:
正负:阴影移动的方向。向右,向下为正值。
大小:阴影移动的距离
-
inset:
正负:表示从哪条边出现阴影。正:左上,负:右下
大小:表示阴影在某一侧的长度
具体内容,可以看下面inset的例子
blur-radius
高斯模糊的半径,从上面例子就可以了解到了。用来设置阴影边缘的模糊的。 不可以为负值。
spread-radius
我们了解了阴影是如何生成的,以及高斯模糊半径的作用范围,现在我们聊一下另一个属性:spread-radius,这个属性称之为扩展半径,扩展二字就很能说明问题了,其实它就是扩展的阴影面积的大小。一开始,阴影的面积是等于元素的尺寸的,我们的模糊半径也只能从这个阴影的边缘两侧开启高斯模糊,当我们想修改这个阴影的面积时,就用到了spread-radius属性。spread-radius表示四个方向增大或者减小的尺寸。 我们修改上面的box-shadow参数,增加扩展半径,去除模糊半径,利于观察
box-shadow: 30px 50px 0 30px #000;
- 绿色:box元素自身的尺寸
- 灰色:未设置扩展半径的阴影区域
- 黑色边框:扩展半径的尺寸
- 虚线区域:每一侧增加的扩展半径 30px 上图其实已经很能说明问题了,黑色边框的高度正好就是30px,正好四个方向,每一个方向都增大30px的长度,那么阴影水平和垂直都增加(30px + 30px)60px 因为扩展半径增大了阴影的面积,所以,模糊半径也会从增大后的阴影边缘向两侧模糊,所以如果设置了模糊半径,效果如下:
box-shadow: 30px 50px 10px 30px #000;
spread-radius 负值
是的,spread-radius是可以设置负数值的,会在水平和垂直方向减小阴影的尺寸。 在后续的场景中,我会详细讲解这个负数值的应用
inset
inset属性在某些场合也用到很多,原理相同,但是细节有些不一样 修改上上面的参数为inset
box-shadow: inset 30px 50px 0 0 #000;
当修改offset为负值时:
box-shadow: inset -30px -50px 0 0 #000;
由上面可以看出,在inset模式下
- offset会选择从哪条边,渲染阴影,这点是不同的
- spread-radius和offset值配合起来的最大值也不能超出元素的尺寸,因为如果超出元素,那么设置这个元素就没有意义了,因为它已经看不见了
四、补充
-
阴影是不会作为内容计算的,这就意味着: 父元素不会因为阴影产生滚动条 不会对布局产生影响,所以阴影可能会覆盖其他元素
-
为什么叫box-shadow
-
表明这只是对盒子的阴影,跟盒子里面的内容没有关系,并不是真正意义的单侧光源阴影,从上面阴影的生成过程就已经就可以了解到,第一步就是生成等同box的阴影,并不会考虑盒子内部是否透明,内部透明是否也能产生阴影,因为阴影会根据盒子裁剪重合的部分。 这也就是它和drop-shadow的区别,后面的应用会具体比较描述。
-
阴影的大小依据,是根据border-box的。 上面的案例,一直没有设置padding和border,所以看不出来,我们可以设置padding,border试试:
.box { width: 300px; height: 200px; background-color: yellowgreen; box-shadow: 30px 50px 0 0 #000; background-clip: content-box; padding: 20px; border: 30px solid red; }
可以看出,阴影的大小是border-box的大小,而不是content-box,包括设置border-radius,也是如此,与border-box保持一致
对于inset,阴影也是从border内边缘扩展
-
-
最后,最重量级的图,w3c给出的box-shadow的示意图 一开始,没展示的原因是,怕一上来就展示大家可能一头雾水,如果你看到这里,再看到这个图,我相信你会豁然开朗。
参考文章:包含但不限于以下文章,如有侵权请联系
https://www.zhangxinxu.com/wordpress/2016/05/css3-filter-drop-shadow-vs-box-shadow/
https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow
下一节,我们将一起了解box-shadow的应用