CSS魔法堂:Box-Shadow没那么简单啦:)
前言
说起box-shadow那第一个想法当然就是用来实现阴影,其实它还能用于实现其他好玩的效果的,本篇就打算说说box-shadow的那些事。
二话不说看效果
3D小球
<style type="text/css">
.ball{
background: rgba(100,100,100,0.2);
width: 100px;
height: 100px;
padding: 10px;
border-radius: 50%;
box-shadow: -14px 8px 100px #333 inset,
0 0 2px #888,
3px -1px 4px #444;
}
</style>
<div class="ball"></div>
纸张阴影(来自@张鑫旭老师)
<style type="text/css">
.curved_box {
display: inline-block;
*display: inline;
width: 200px;
height: 248px;
margin: 20px;
background-color: #fff;
border: 1px solid #eee;
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 60px rgba(0, 0, 0, 0.06) inset;
-moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;
position: relative;
*zoom: 1;
}
.curved_box:before {
-webkit-transform: skew(-15deg) rotate(-6deg);
-moz-transform: skew(-15deg) rotate(-6deg);
transform: skew(-15deg) rotate(-6deg);
left: 15px;
}
.curved_box:after {
-webkit-transform: skew(15deg) rotate(6deg);
-moz-transform: skew(15deg) rotate(6deg);
transform: skew(15deg) rotate(6deg);
right: 15px;
}
.curved_box:before, .curved_box:after {
width: 70%;
height: 55%;
content: ' ';
-webkit-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
-moz-box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
position: absolute;
bottom: 10px;
z-index: -1;
}
</style>
<div class="curved_box"></div>
细读属性
看到上面这么绚丽的效果,是不是迫不及待想弄清box-shadow呢?下面我们来一步步解密它吧!
概述属性语法
box-shadow: none | <shadow>[,<shadow>]*
默认值为none
<shadow>
:inset? && <length>{2,4} && <color>?
shadow pattern,默认为outset,即采用outer box-shadow。通过设置为inset时,则采用inner box-shadow。
horizontal offset,阴影距离原位置的水平位移,正数表示向右移动,负数表示向左移动。
vertical offset,阴影距离原位置的垂直位移,正数表示向下移动,负数表示向上移动。
blur radius,默认值为0,阴影模糊度半径。
spread distance,默认值为0,扩展或缩小阴影的作用面积。
<color>
,阴影颜色,默认与color
属性一致。
注意:我们可以同时设置多个阴影,而阴影的z-index值从左向右递减。
outer box-shadow 和 inner box-shadow怎么玩?
默认情况下采用的是outer box-shadow,当在box-shadow
中添加inset关键词后,则采用inner box-shadow了,但到底它俩的效果是如何的呢?
<style type="text/css">
.box{
float: left;
background: #888;
width: 100px;
height: 100px;
margin-right: 20px;
}
.outer-box-shadow{
box-shadow: 10px 10px #F00;
}
.inner-box-shadow{
box-shadow: 10px 10px #F00 inset;
}
</style>
<div class="box outer-box-shadow"></div>
<div class="box inner-box-shadow"></div>
</div>
outer-box-shadow
特点:阴影落在元素的border box之外。
实现原理:
- 创建一个与元素border box尺寸一致的阴影盒子;
- 将阴影盒子定位到于元素border box重合,并位于元素之下;
- 根据
horizontal offset
和vertical offset
来相对原位置作移动; - 根据
spread distance
缩放阴影盒子的尺寸(会影响盒子的位移); - 根据
blur radius
对阴影盒子作加工; - 最后将阴影盒子与元素border box重合部分剪切掉。
<style type="text/css">
.box{
background: #888;
width: 100px;
height: 100px;
}
.outer-box-shadow{
box-shadow: 90px 10px #F00;
}
</style>
<div class="box outer-box-shadow"></div>
</div>
模拟一下:
<style type="text/css">
.box{
position: relative;
}
.box-shadow{
position: absolute;
z-index: -1;
background: #F00;
width: 100px;
height: 100px;
left: 20px;
top: 20px;
}
.box-content{
background: #888;
width: 100px;
height: 100px;
}
</style>
<div class="box">
<div class="box-shadow"></div>
<div class="box-content"></div>
</div>
inner-box-shadow
特点:阴影落在元素的padding box之内。
实现原理(纯个人理解):
- 创建一个与元素padding box尺寸一致的阴影盒子;
- 将阴影盒子定位到于元素padding box重合,并位于元素之上;
- 水平和垂直各画两条线,分别跟元素padding edge重合;(共4条分别记为left/top/right/bottom-guideline)
- 根据
horizontal offset
和vertical offset
移动left/top/right/bottom-guideline。 - 根据
spread distance
移动4条线。spread distance为正数时,left-guideline向右移动,top-guideline向下移动,right-guideline向左移动和bottom-guidelien向上移动;spread distance为负数时,则相反。 - 根据
blur radius
加工元素各padding edge至其对应的guideline间的区域. - 对阴影盒子进行剪裁
- 剪切掉不与元素padding box重叠的部分;
- 仅显示元素各padding edge至其对应的guideline间的区域。
<style type="text/css">
.box{
float: left;
background: #888;
width: 100px;
height: 100px;
margin-right: 10px;
}
.box1{
box-shadow: 0 0 0 20px red inset;
}
.box2{
box-shadow: 10px 0 0 20px red inset;
}
.box3{
box-shadow: 10px 0 10px 20px red inset;
}
.box4{
box-shadow: 0 0 10px 50px red inset;
}
</style>
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
<div class="box box4"></div>
模拟一下:
<style type="text/css">
.box-shadow{
position: relative;
display: inline-block;
background: red;
overflow: hidden;
}
.bg{
position: absolute;
background: #888;
left: 30px;
right: 10px;
top: 20px;
bottom: 20px;
}
.content{
position: relative;
z-index: 1;
width: 80px;
height: 80px;
padding: 20px;
}
</style>
<div class="box-shadow">
<div class="bg"></div>
<div class="content"></div>
</div>
模糊边框 by blur radius
W3C spec中没有规定浏览器厂商使用哪种方式实现模糊效果,反正效果与高斯模糊效果差不多就是了。但有一点我们需要注意的,那就是模糊效果会扩大阴影的面积。
<style type="text/css">
.outline{
border: 1px solid red;
margin: 40px 0;
}
.s{
background: rgba(255, 100, 100, 0.1);
width: 100px;
height: 100px;
}
.s1{
box-shadow: 110px 0 0 #333;
}
.s2{
box-shadow: 110px 0 20px #333;
}
.s3{
box-shadow: 110px 0 40px #333;
}
</style>
<div class="outline">
<div class="s s1">sample1</div>
</div>
<div class="outline">
<div class="s s2">sample2</div>
</div>
<div class="outline">
<div class="s s3">sample3</div>
</div>
sample1是blur radius
为0的效果,可以看到阴影尺寸与元素尺寸一模一样。而sample2是blur radius
为20px的效果,可以看到阴影尺寸有所扩展了,而sample3则扩展得更多一些。
现在我们感性上认知到blur radius
值大于0时会扩展阴影尺寸,那么到底扩展多少呢?那我们要先明确模糊发生的起始位置了。
- 对于outer-shadow-box而言,模糊发生的起始位置就是阴影盒子的各边;
- 对于inner-shadow-box而言,模糊发生的起始位置就是各guideline。
然后模糊效果是从发生的位置,对于水平方向的边或guideline则向垂直方向发散,对于垂直方向的边或guideline则向水平方向发散,且发散的距离相同。
发散的距离相同,因此每个方向各发散为blur radius/2
的距离。看sample3中阴影尺寸已经与元素盒子重叠了,因为阴影盒子左边框向左发散了20px了,超过它俩之间10px的水平距离了,而sample2则恰恰邻近而已。
缩放阴影尺寸 by spread distance
如果说blur radius
是暗地里扩大阴影的尺寸,那么spread distance
则是明目张胆地缩放阴影的尺寸了。
<style type="text/css">
.outline{
border: 1px solid red;
margin: 40px 0;
}
.s{
background: rgba(255, 100, 100, 0.1);
width: 100px;
height: 100px;
}
.s1{
box-shadow: 110px 0 0 #333;
}
.s2{
box-shadow: 110px 0 0 10px #333;
}
.s3{
box-shadow: 110px 0 0 -10px #333;
}
</style>
<div class="outline">
<div class="s s1">sample1</div>
</div>
<div class="outline">
<div class="s s2">sample2</div>
</div>
<div class="outline">
<div class="s s3">sample3</div>
</div>
还记得《CSS魔法堂:重拾Border之——解构Border》中提及通过border-top/right/bottom/left-colors
实现彩虹边框吗?由于兼容性问题和1px对应一种color的缘故,实际应用得很少,但通过outer-box-shadow和spread distance
我们就可以得到效果更好,兼容性很高的实现方案了。
<style type="text/css">
.rainbow{
margin: 50px;
width: 100px;
height: 100px;
box-shadow: 0 0 0 2px rgb(255,0,0),
0 0 0 5px rgb(255,165,0),
0 0 0 8px rgb(255,255,0),
0 0 0 10px rgb(0,255,0),
0 0 0 12px rgb(0,127,255),
0 0 0 15px rgb(0,0,255),
0 0 0 20px rgb(139,0,255);
}
</style>
<div class="rainbow"></div>
弄清各图层的z-index
上图可以看到没有阴影时,各图层的z-index顺序。那么阴影呢?
- 对于outer-box-shadow,则其z-index高于margin图层,低于background-color图层;
- 对于inner-box-shadow,则其z-index高于padding图层,低于content图层。
阴影的position
通过horizontal/vertical offset
重定位阴影盒子,通过blur radius
或spread distance
缩放阴影盒子的尺寸,但请注意的是阴影盒子不影响其他盒子的布局,其实阴影盒子就相当于采用absolute定位一样,不会占据Normal flow的空间,也不会影响其他元素的布局,因此仅修改阴影位置或尺寸时,只会触发repaint,而不会触发reflow。
圆角or直角box-shadow傻傻分不清楚?
阴影不仅默认尺寸与元素盒子一致,默认形状也一致。也就是元素盒子采用圆角时,阴影的默认形状也是圆角的。既然说是默认形状一致,就是说可以不一致咯!那到底如何不一致呢,下面我们一起来看个究竟吧!
<style type="text/css">
.s1{
background: #0EF;
width: 100px;
height: 100px;
border-radius: 10px;
box-shadow: 110px 0 0 -10px #333,
220px 0 0 0 #666,
360px 0 0 20px #888;
}
</style>
<div class="s1">sample1</div>
当设置spread distance
后,border-radius的值也将随之变化,具体公式为border-radius + spread-distance * (1 + (border-radius / spread-distance - 1)^3)
。
因此spread distance
为正数时,border-radius会变大; 而spread distance
为负数时,border-radius会减小,直至为0px为止。
被割裂的box-shadow
当设置box-shadow的盒子被拆分为多个盒子时,其对应的box-shadow又会如何呢?其实这不仅仅是box-shadow的问题,如border、background-image等均会遇到同样的问题。CSS3中引入一个新特性box-decoration-break
来设置上述情况时的渲染效果。
box-decoration-break: slice | clone
slice是默认值,表示首先按未拆分时的状态渲染border、background-image等样式,然后再将其直接拆分为多个盒子;
clone表示首先将其直接拆分为多个盒子,然后再逐个盒子渲染border、background-image等样式。
<style type="text/css">
.intro{
font-size: 14px;
line-height: 1.5;
text-indent: 1em;
width: 300px;
}
.intro span{
border: 1px solid #666;
border-radius: 5px;
box-shadow: 5px 3px 3px #AAA;
}
.slice{
-webkit-box-decoration-break: slice;
}
.clone{
-webkit-box-decoration-break: clone;
}
</style>
<p class="intro">
<span class="slice">
Hey there, welcome to be here to share something aboute CSS together:) My name is fsjohnhuang, a FE from Midea. Enjoy the evolution of FE, and feel excited in the work I'm doing now.
</span>
</p>
<p class="intro">
<span class="clone">
Hey there, welcome to be here to share something aboute CSS together:) My name is fsjohnhuang, a FE from Midea. Enjoy the evolution of FE, and feel excited in the work I'm doing now.
</span>
</p>
从上面可以看到,与其说box-decoration-break
的属性值影响box-shadow
的效果,还不如说是box-decoration-break
的属性值影响border-radius
和border
作用到元素盒子的效果,然后由盒子的效果再间接影响box-shadow
的效果。
兼容性
IE和Edge均不支持,FF支持得最好,而Webkit内核的则要加-webkit-前缀。
对于不支持的浏览器,其效果如同box-decoration-break:slice
兼容性
IE9都支持box-shadow
多让人可喜可贺的消息啊(因为我工作中只需兼容IE9+就Ok了:))。但IE6~8呢?方案很多啦,上面也有简单的介绍到。@张鑫旭老师提到在模拟blur radius效果时,采用以下方案
.ieBlock{
height:100px;
width:100px;
background:#000;
filter:progid:DXImageTransform.Microsoft.Blur(pixelradius=10);
-ms-filter:"progid:DXImageTransform.Microsoft.Blur(pixelradius=10)";
}
要比采用以下方案要好!
.shadow {
-moz-box-shadow: 3px 3px 4px #000;
-webkit-box-shadow: 3px 3px 4px #000;
box-shadow: 3px 3px 4px #000;
/* For IE 8 */
-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000')";
/* For IE 5.5 - 7 */
filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000');
}
另外若想不假思索地用到生产环境中,还是用成熟的CSS库较好。具体请参考
PIE使IE支持CSS3圆角盒阴影与渐变渲染
总结
尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/5477194.html_肥仔John
感谢
the-box-shadow
break-decoration
CSS3 box-shadow实现纸张的曲线投影效果
CSS实现跨浏览器兼容性的盒阴影效果
CSS实现跨浏览器的box-shadow盒阴影效果(2)
PIE使IE支持CSS3圆角盒阴影与渐变渲染
《图解CSS3核心技术与案例实战》 —— 3.5 CSS3盒子阴影属性
CSS魔法堂:Box-Shadow没那么简单啦:)的更多相关文章
- CSS魔法堂:小结一下Box Model与Positioning Scheme
前言 对于Box Model和Positioning Scheme中3种定位模式的细节,已经通过以下几篇文章记录了我对其的理解和思考. <CSS魔法堂:重新认识Box Model.IFC.B ...
- CSS魔法堂:说说Float那个被埋没的志向
前言 定位系统中第一难理解就是Normal flow,而第二就非Float莫属了,而Float难理解的原因有俩,1. 一开头我们就用错了:2. 它跟Normal flow靠得太近了.本文尝试理清Fl ...
- CSS魔法堂:更丰富的前端动效by CSS Animation
前言 在<CSS魔法堂:Transition就这么好玩>中我们了解到对于简单的补间动画,我们可以通过transition实现.那到底多简单的动画适合用transtion来实现呢?答案就是 ...
- CSS魔法堂:"那不是bug,是你不懂我!" by inline-block
前言 每当来个需要既要水平排版又要设置固定高宽时,我就会想起display:inline-block,还有为了支持IE5.5/6/7的hack*display:inline;*zoom:1;.然后发 ...
- CSS魔法堂:Absolute Positioning就这个样
前言 当我们以position:absolute之名让元素脱离Normal flow的控制后,以为通过left和top属性值即可让元素得以无限的自由时,却发现还有各种神秘的力量左右着它的来去,于是我们 ...
- CSS魔法堂:深入理解line-height和vertical-align
前言 一直听说line-height是指两行文本的基线间的距离,然后又说行高等于行距,最近还听说有个叫行间距的家伙,@张鑫旭还说line-height和vertical-align基情四射,贵圈真乱啊 ...
- CSS魔法堂:不得不说的Containing Block
前言 <CSS魔法堂:重新认识Box Model.IFC.BFC和Collapsing margins>中提到在没有floated兄弟盒子时,line box的左右边框会与所属的cont ...
- CSS魔法堂:hasLayout原来是这样!
前言 过去一直听说旧版本IE下很多诡异bug均由一个神秘角色引起的,那就是hasLayout.趁着最近突然发神经打算好好学习CSS,顺便解答多年来的疑惑. hasLayout到底是何方神圣? hasL ...
- CSS魔法堂:display:none与visibility:hidden的恩怨情仇
前言 还记得面试时被问起"请说说display:none和visibility:hidden的区别"吗?是不是回答完display:none不占用原来的位置,而visibilit ...
随机推荐
- linux 中部署ant编译的包中缺少问题
今天遇到在window上部署ant编译的包,能运行正常,但部署在linux中出现跳不进jsp中,出现404问题,后来经过排查在jsp中<%@taglib prefix="c" ...
- Mysql修改root密码
一.启动命令行,输入: taskkill /f /im mysqld.exe //关闭mysql 二.转入mysql的bin目录下 三.输入:mysqld --skip-grant-tables // ...
- 体验phonegap3.0
网上有各种各样的phonegap环境搭建资料,鉴于学习和整理的考虑,我还是把我搭建的过程整理出来 这篇文章中将涉及到的内容 PhoneGap环境需要的组件 Node环境 JDK Android SDK ...
- 减小ipa体积之删除frameWork中无用mach-O文件
最近项目末期, 我们团队为了ipa的大小使用不少的体积减小的方法, 除了一些常规的方法之外, 我分享一下自己研究出来的新思路. 首先我们来简单的介绍一下mach-O. 什么是mach-O? Mach- ...
- 有点担心Node.js的未来了
原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com 首先本文的目的不是引发语言之争,纯属个人的一些思绪记录. 因为工作原因,用Node.js做过几个项目,基本都是涉及 ...
- 谁占了我的端口 for Windows
这篇文章发布于我的 github 博客:原文 今天在本地调试 Blog 的时候意外的出现了一些错误:127.0.0.1 4000 端口已经被其他的进程占用了.如何找到占用端口的进程呢? Configu ...
- HTML中em与b等的区别
最近在学习HTML基本知识,看到b标签和strong还有em,都是表示强调目的的,那他们之间的区别是什么呢?总结如下: < b > < i > 是视觉要素(presentati ...
- 【PRINCE2是什么】PRINCE2认证之七大原则(4)
我们先来回顾一下,PRINCE2七大原则分别是持续的业务验证,经验学习,角色与责任,按阶段管理,例外管理,关注产品,剪裁. 第四个原则:按阶段管理. 阶段管理其实是给高层提供了项目生命周期中相对应的控 ...
- 2013 duilib入门简明教程 -- 结合win32和MFC (16)
虽然duilib自带在MFC中使用duilib的Demo,但只是MFC窗口和duilib窗口不重叠的情况.如果要在MFC窗口中嵌入duilib控件,或者在duilib控件中嵌入MFC的控件的话 ...
- fir.im Weekly - 暖心的 iOS 持续集成,你值得拥有
一则利好消息,flow.ci 支持 iOS 项目持续集成,想试试的伙伴去 Gitter群 问问.首批尝鲜用户@阿米amoy 已经用 flow.ci 实现了基本的 iOS 持续集成,并详细记录整个 Bu ...