参考:http://www.cnblogs.com/fsjohnhuang/p/5477194.html
1. 属性概述
box-shadow : none | <shadow>[, <shadow>]*
默认值为none
<shadow> : inset? && <length>{2, 4} && <color>?
参数 | 描述 |
---|---|
shadow pattern | 默认为outset,即阴影在边框外部;若为inset,则阴影在边框内部 |
horizontal offset | outset 模式下:阴影距离原位置的水平位移,正数向右,负数向左 inset 模式下:正数从左开始,负数从右开始 |
vertical offset | outset 模式下:阴影距离原位置的垂直位移,正数向下,负数向上 inset 模式下:正数从上开始,负数从下开始 |
blur radius | 默认值为0,表示阴影模糊度半径 |
spread distance | 默认值为0,用来扩展或缩小阴影的作用面积 |
color | 如果不填,默认为元素的 color 值 |
2. (outset vs inset) & (horizontal offset vs vertical offset)
outset 模式下,位移从左上到右下
inset 模式下:正数从左上角开始向内,负数从右下角开始向内
blur不支持负数
<!DOCTYPE html>
<html>
<head>
<style>
.box {
width: 10em;
height: 10em;
margin-top: 2em;
margin-left: 2em;
border: 1px solid black;
display: inline-block;
padding: 1em;
color: blue;
}
.box:nth-child(1) {
box-shadow: 1em 1em 0 0;
}
.box:nth-child(2) {
box-shadow: -1em -1em 0 0;
}
.box:nth-child(3) {
box-shadow: 1em 1em 0 0 inset;
}
.box:nth-child(4) {
box-shadow: -1em -1em 0 0 inset;
}
.box:nth-child(5) {
box-shadow: 1em 1em 0 -0.5em; /* spread负数等价于"将offset加上负数的spread,如果最终结果小于0那么不显示" */
}
.box:nth-child(6) {
box-shadow: 1em 1em -1em 0; /* blur不支持负数 */
}
</style>
</head>
<body>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</body>
</html>
3. blur & spread
blur 指的是从边框开始,分别向内向外一共进行多少像素的高斯模糊(内外各一半),不支持负数
spread 指的是阴影从边界向外部延伸的距离
当设置 spread distance 后,border-radius 的值也将会随之变化,具体公式为
border-radius + spread-distance * (1 + (border-radius / spread-distance - 1)^3)
因此当 spread distance 为负数时,border-radius 会减小,直至为 0px (不显示)为止
<!DOCTYPE html>
<html>
<head>
<style>
body {
padding-top: 2em;
}
#container {
border: 1px solid black;
width: 100%;
padding-top: 1em;
padding-bottom: 1em;
}
#content {
border: 1px solid black;
width: 100%;
height: 10em;
}
#content>div {
width: 10em;
height: 100%;
margin-left: 4em;
background-color: gray;
border: 1px solid red;
display: inline-flex;
/* 水平居中 */
justify-content: center;
/* 垂直居中 */
align-items: center;
}
#content>div:nth-child(1) {
box-shadow: 0 0 1em 2em blue;
}
#content>div:nth-child(2) {
box-shadow: 0 0 1em 2em blue;
}
#content>div:nth-child(4) {
box-shadow: 0 0 2em 2em blue;
}
#content>div:nth-child(3) {
box-shadow: 0 0 2em 2em blue;
}
#content>div:nth-child(5) {
box-shadow: 0 0 0 2em blue;
}
#content>div:nth-child(6) {
box-shadow: 0 0 0 2em blue;
}
#content>div:nth-child(7) {
box-shadow: 0 0 2em 0 blue;
}
#content>div:nth-child(8) {
box-shadow: 0 0 2em 0 blue;
}
</style>
</head>
<body>
<div id="container"><div id="container"><div id="container"><div id="container">
<div id="content">
<div>blur: 1em<br>spread: 2em</div>
<div>blur: 1em<br>spread: 2em</div>
<div>blur: 2em<br>spread: 2em</div>
<div>blur: 2em<br>spread: 2em</div>
<div>blur: 0<br>spread: 2em</div>
<div>blur: 0<br>spread: 2em</div>
<div>blur: 2em<br>spread: 0</div>
<div>blur: 2em<br>spread: 0</div>
</div>
</div></div></div></div>
</body>
</html>
4. shadow 的形状 & 叠加 & 盒子各层的 z-index
- outset(默认):z-index 高于 margin 图层,低于 background-color 图层
- inset:z-index 高于 padding 图层,低于 content 图层。
阴影盒子不影响其它盒子的布局,阴影盒子就相当于采用absolute定位一样,不会占据Normal flow 的空间,也不会影响其它元素的布局,因此仅修改阴影位置或尺寸,只会触发 repaint,而不会触发 reflow。
另外,阴影的形状与盒子一致。如果盒子是带圆角的,那么阴影就也是圆角的
<!DOCTYPE html>
<html>
<head>
<style>
body {
padding: 5em;
}
div {
border: 1px solid black;
}
.shadow {
width: 5em;
height: 5em;
display: inline-block;
padding: 1em;
background-color: lightgray;
vertical-align:middle;
box-shadow: inset -1em -1em 0 0,
0 0 0 1em hsl(0, 100%, 50%),
0 0 0 2em hsl(60, 100%, 50%),
0 0 0 3em hsl(120, 100%, 50%),
0 0 0 4em hsl(180, 100%, 50%),
0 0 0 5em hsl(240, 100%, 50%);
}
.reference {
width:5em;
height:10px;
background-color:black;
display:inline-block;
vertical-align:middle;
}
</style>
</head>
<body>
<div>
<div class="shadow">Shadow</div>
<div class="reference"></div>
<div class="shadow" style="margin-left:10em; border-radius:50%">Shadow</div>
<div class="reference"></div>
</div>
</body>
</html>
5. 割裂的 shadow
只有 display : inline
的元素由于父盒子宽度有限被割裂的情况下才会显示出如下效果。
slice 是默认值,表示首先按未拆分时的状态渲染border、background-image等样式,然后再将其直接拆分为多个盒子;
clone 表示首先将其直接拆分为多个盒子,然后再逐个盒子渲染border、background-image等样式。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<style>
.box {
margin: 1em;
width: 20em;
display: inline-block;
vertical-align: top;
line-height: 2;
}
.shadow {
border: 1px solid black;
/* 用具体值的好处是水平半径=垂直半径;如果用百分比,由于宽高的不同,横和竖向的弧度就会不同;如果做圆形直接50%即可 */
border-radius: 5px;
box-shadow: 5px 3px 3px #AAA;
}
.box:nth-child(3) > .shadow {
box-decoration-break: slice;
}
.box:nth-child(4) > .shadow {
box-decoration-break: clone;
}
</style>
</head>
<body>
<!--
block元素是一个整体,有宽高的概念,所以边框也呈一个整体;
块级元素默认宽度为父元素的整个宽度
浮动元素的默认宽度为 能包含其内容的最小宽度
而内联元素,由于每行的长度都不尽相同,因此每行都有自己的行宽(或者称为行框)
-->
<div class="box shadow">
我想很多人都有坐拥书城的梦想,不是装门面,不是显摆,而是证明自己不孤独。因为,与一本书的缘份还在,梦想就不曾离去。
</div>
<!-- inline的元素没有宽度这个概念(block才有所谓的宽高),所以要在外面框一层 -->
<div class="box">默认(box-decoration-break : slice):<br>
<div class="shadow" style="display: inline">生活从来都是不公平的,不是每个姑娘都有水晶鞋穿,不是每匹白马都能被王子骑,认识到这世间的不公平,并且接受这些不公平的时候,世界才刚刚开始原谅我们的幼稚。所以,好好吃饭,好好睡觉,人一辈子也就年轻一次。谁没幼稚过呢,不过有的人幼稚就是呆萌,有的人幼稚就是脑残,这世界还是真的不公平啊。
</div>
</div>
<div class="box">box-decoration-break : slice:<br>
<span class="shadow"> 不要总是谈钱,为什么要谈钱呢。现在的年轻人,一说工作就谈钱,你工作就是为了赚钱吗?不是,你工作是为了民族崛起而工作,你工作是为了祖国的未来而奋斗。少年强,则中国强,不要问老板给你开多少工资,而是要问你能为社会做多少贡献,不是金钱在驱使你,而是整个时代在召唤你。
</span>
</div>
<div class="box">box-decoration-break : clone:<br>
<span class="shadow">不要提钱,真正的财富是你看不见的,它不是银行卡上冰冷的数字,也不是你每个月领到的工资,更不是想买就买的放肆,是能力,是知识,是你什么时候能成为一个对社会有用的人。
</span>
</div>
</body>
</html>
6. 应用
(1)3D小球
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<style>
body {
font-size: 100%;
}
.three-dimensional-ball {
width: 10em;
height: 10em;
display: inline-block;
margin: 2em;
border-radius: 50%;
background-color: #6662; /* 背景色在内阴影的下层,阴影没完全覆盖的地方会透出来,这里是高光出的叠加颜色 */
padding: 1em;
box-shadow: -1.5em 1em 7em #333 inset, /* 阴影从右上角开始向内弥漫,blur=6表示内外各3 */
0 0 .2em #888, /* 描上一层类似光晕的边 */
.5em -.1em 1em #444; /* 在右上角的边框外绘制阴影(外边框会造成接口处白色锯齿) */
}
</style>
</head>
<body>
<div class="three-dimensional-ball"></div>
</body>
</html>
(2)纸张
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<style>
body {
font-size: 100%;
}
.curve-paper {
width: 12em;
height: 16em;
position: relative;
margin: 1em;
display:inline-block;
background-color: white;
border: 1px solid #eee;
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset; /* 这里分别用来模拟纸张的外阴影,和内部反射的阴影颜色 */
}
.curve-paper::before, .curve-paper::after { /* before和after用来作纸张的两个角的阴影 */
content: '';
width: 70%;
height: 50%;
position: absolute;
border: 1px solid black;
bottom: .5em;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
z-index: -1;
}
.curve-paper::before {
left: 1em;
transform: skew(-18deg) rotate(-8deg); /* 函数的先后顺序不同,变化的结果就不同(不符合交换律) */
}
.curve-paper::after {
right: 1em;
transform: skew(10deg, 7deg)
}
.curve-test {
border: 1px dashed black;
box-shadow: 1px 1px 4px green, 0 0 40px blue inset;
}
.curve-test::before, .curve-test::after {
z-index: 0 !important; /* !important表示优先显示,但由于该style在后面,所以本身就会覆盖前面的style,所以不需要用!important */
border: 1px dashed black;
box-shadow: 0 8px 16px red;
}
</style>
</head>
<body>
<div class="curve-paper"></div>
<div class="curve-paper curve-test"></div>
</body>
</html>