资讯专栏INFORMATION COLUMN

CSS魔法堂:Box-Shadow 没那么简单啦:)

Galence / 1867人阅读

摘要:阴影距离原位置的垂直位移,正数表示向下移动,负数表示向上移动。实现原理纯个人理解创建一个与元素尺寸一致的阴影盒子将阴影盒子定位到于元素重合,并位于元素之上水平和垂直各画两条线,分别跟元素重合共条分别记为根据和移动。

前言

说起box-shadow那第一个想法当然就是用来实现阴影,其实它还能用于实现其他好玩的效果的,本篇就打算说说box-shadow的那些事。

二话不说看效果


3D小球



纸张阴影(来自@张鑫旭老师)


细读属性

看到上面这么绚丽的效果,是不是迫不及待想弄清box-shadow呢?下面我们来一步步解密它吧!

概述属性语法
box-shadow: none | [,]*

默认值为none

`:`inset? && {2,4} && ?

shadow pattern 默认为outset,即采用outer box-shadow。通过设置为inset时,则采用inner box-shadow。

horizontal offset 阴影距离原位置的水平位移,正数表示向右移动,负数表示向左移动。

vertical offset 阴影距离原位置的垂直位移,正数表示向下移动,负数表示向上移动。

blur radius 默认值为0,阴影模糊度半径。

spread distance 默认值为0,扩展或缩小阴影的作用面积。

阴影颜色,默认与color属性一致。

注意:我们可以同时设置多个阴影,而阴影的z-index值从左向右递减。

outer box-shadow 和 inner box-shadow怎么玩?

默认情况下采用的是outer box-shadow,当在box-shadow中添加inset关键词后,则采用inner box-shadow了,但到底它俩的效果是如何的呢?


outer-box-shadow

特点:阴影落在元素的border box之外。

实现原理:

创建一个与元素border box尺寸一致的阴影盒子;

将阴影盒子定位到于元素border box重合,并位于元素之下;

根据horizontal offsetvertical offset来相对原位置作移动;

根据spread distance缩放阴影盒子的尺寸(会改变盒子的位移);

根据blur radius对阴影盒子作加工;

最后将阴影盒子与元素border box重合部分剪切掉。


模拟一下:


inner-box-shadow

特点:阴影落在元素的padding box之内。

实现原理(纯个人理解):

创建一个与元素padding box尺寸一致的阴影盒子;

将阴影盒子定位到于元素padding box重合,并位于元素之上;

水平和垂直各画两条线,分别跟元素padding edge重合;(共4条分别记为left/top/right/bottom-guideline)

根据horizontal offsetvertical 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间的区域。


模拟一下:


模糊边框 by blur radius

W3C spec中没有规定浏览器厂商使用哪种方式实现模糊效果,反正效果与高斯模糊效果差不多就是了。但有一点我们需要注意的,那就是模糊效果会扩大阴影的面积


sample1
sample2
sample3

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则是明目张胆地缩放阴影的尺寸了。


sample1
sample2
sample3

还记得《CSS魔法堂:重拾Border之——解构Border》中提及通过border-top/right/bottom/left-colors实现彩虹边框吗?由于兼容性问题和1px对应一种color的缘故,实际应用得很少,但通过outer-box-shadow和spread distance我们就可以得到效果更好,兼容性很高的实现方案了。


弄清各图层的z-index

上图可以看到没有阴影时,各图层的z-index顺序。那么阴影呢?

对于outer-box-shadow,则其z-index高于margin图层,低于background-color图层;

对于inner-box-shadow,则其z-index高于padding图层,低于content图层。

阴影的position

通过horizontal/vertical offset重定位阴影盒子,通过blur radiusspread distance缩放阴影盒子的尺寸,但请注意的是阴影盒子不影响其他盒子的布局,其实阴影盒子就相当于采用absolute定位一样,不会占据Normal flow的空间,也不会影响其他元素的布局,因此仅修改阴影位置或尺寸时,只会触发repaint,而不会触发reflow。

圆角or直角box-shadow傻傻分不清楚?

阴影不仅默认尺寸与元素盒子一致,默认形状也一致。也就是元素盒子采用圆角时,阴影的默认形状也是圆角的。既然说是默认形状一致,就是说可以不一致咯!那到底如何不一致呢,下面我们一起来看个究竟吧!


sample1

当设置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等样式。


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.

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.

从上面可以看到,与其说box-decoration-break的属性值影响box-shadow的效果,还不如说是box-decoration-break的属性值影响border-radiusborder作用到元素盒子的效果,然后由盒子的效果再间接影响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盒子阴影属性

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/115237.html

相关文章

  • CSS魔法:重拾Border之——更广阔的遐想

    摘要:也就是说我们操作的几何公式中的未知变量,而具体的画图操作则由渲染引擎处理,而不是我们苦苦哀求设计师帮忙。 前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-top-left/right-radius的水平半径之和大于元素宽度时,实际值会按比...

    lily_wang 评论0 收藏0
  • CSS魔法:改变单选框颜色就这么吹毛求疵!

    摘要:前言是否曾经被业务提出能改改这个单选框的颜色吧让它和主题颜色搭配一下吧,然后苦于原生不支持换颜色,最后被迫自己手撸一个凑合使用。设置为的样式行为特征单选框的行为特征,明显就是选中与否,及选中状态的改变事件,因此我们必须保持对外提供事件。 前言  是否曾经被业务提出能改改这个单选框的颜色吧!让它和主题颜色搭配一下吧!,然后苦于原生不支持换颜色,最后被迫自己手撸一个凑合使用。若抛开inpu...

    freecode 评论0 收藏0
  • CSS魔法:那个被我们忽略的outline

    摘要:真心没法弄出圆角自从有了后,我们就可以通过制作圆角矩形圆形等图形,甚至连也受到影响从而实现元素阴影也能做到圆角的效果。那么是否也能做出圆角的效果呢答案是否定的。 前言  在CSS魔法堂:改变单选框颜色就这么吹毛求疵!中我们要模拟原生单选框通过Tab键获得焦点的效果,这里涉及到一个常常被忽略的属性——outline,由于之前对其印象确实有些模糊,于是本文打算对其进行稍微深入的研究^_^ ...

    Rocko 评论0 收藏0
  • CSS魔法:display:none与visibility:hidden的恩怨情仇

    摘要:不耽误表单提交数据虽然我们无法看到的元素,但当表单提交时依然会将隐藏的元素的值提交上去。让元素在见面上不可视,但保留元素原来占有的位置。不过由于各浏览器实现效果均有出入,因此一般不会使用这个值。继承父元素的值。 前言  还记得面试时被问起请说说display:none和visibility:hidden的区别吗?是不是回答完display:none不占用原来的位置,而visibilit...

    selfimpr 评论0 收藏0
  • CSS魔法:更丰富的前端动效by CSS Animation

    摘要:无效生效重复怎么办与规则一样,标准规定相同的关键帧不产生层叠,仅最后出现的认定为有效。但实际上和均将关键帧设计为可层叠的。为默认值,表示动画一结束,动画效果就结束表示动画一开始就马上执行完第一个关键帧的效果。 前言  在《CSS魔法堂:Transition就这么好玩》中我们了解到对于简单的补间动画,我们可以通过transition实现。那到底多简单的动画适合用transtion来实现呢...

    MrZONT 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<