二、CSS3里的阴影
1、盒阴影 box-shadow
W3C关于盒阴影的定义放在<CSS3背景与边框模块>(CSS Backgrounds and Borders Module Level 3),是今年2月才成为候选推荐标准的(W3C Candidate Recommendation )。
其中,<shadow> = inset? && [ <length>{2,4} && <color>? ],关于各参数的说明:
inset是可选参数,加上就变成内阴影了;
第一个length是阴影的偏移水平。正值阴影向右偏移,负值向左偏移,就是上面计算过的X( = - cosθ * D);
第二个length是垂直偏移。正值阴影向下偏移,负值向上偏移,就是上面计算过的Y( = sinθ1 * D);
第三个length是阴影的模糊半径。如果为零,阴影的边缘锋利。否则,该值越大,阴影的边缘越模糊。
注1. W3C 规定此项不能取负值,实际Chrome和Safari在负值情况下阴影也会生效,但是会有收缩阴影的作用,就是说原本有10px的扩展,模糊半径使用了-5px,那么实际看到的只有5px锋利的扩展的阴影了。
注2. 此模糊半径是在半径为0的锋利阴影基础上,向内向外各模糊一半的距离。例如,如果设置模如糊半径是10px,于是阴影会在原有基础上向外扩张5px,向内收缩5px,在此10px范围内渲染模糊 —— 这并不是一个精确值,在某些取值下会有偏差。
注3.这里的模糊半径是以px为单位,跟Photosho中百分数的扩展属性单位也不同,并且恰好相反的是,这个值越大,阴影的模糊半径越大——不过他们的作用确实是一样的
第四个length是扩展距离。正值在各个方向扩展指定的半径。负值导致收缩阴影的形状。请注意内在的阴影,扩大了阴影(创造更多的阴影区域)指收缩阴影的边缘形状。这个值就是Photoshop中的大小(size)值;
color就是是阴影的色值了,可以用rgba格式,设置有透明度的颜色。
由于浏览器渲染CSS3盒阴影属性模糊半径的方式跟Photoshop中投影扩展的区别,造成这两者之间的转换会有难度。目前制作经理多是凭观察、微调来设置这个值。实际使用时可以测量Photoshop中产生的模糊半径范围(通过调整Photoshop 投影面板中的扩展属性等),比如,在Photoshop中由扩展属性造成了10px宽的模糊区域,CSS里这一项值即可设置为10px。但由于浏览器在渲染这10px模糊时是同时向内和向外各模糊5px,为保持阴影范围,需要把扩展距离或对象的尺寸缩小5px。
并且,与Photoshop的投影不同,在没有扩展距离的情况下,对象也能对投影进行模糊渲染。
注意:
前两个length--阴影偏移量必须定义,inset和模糊半径、扩展距离、颜色参数都是可选项。
可多个阴影累加,先定义的阴影叠在后定义的上面,如:
.shadow{box-shadow:5px 5px #ff0,5px 5px 0px 10px #00f,5px 5px 5px 20px #0f0,5px 5px 10px 30px #f00;}
.shadow{box-shadow:5px 5px #ff0,5px 5px 0px 10px #00f,5px 5px 5px 20px #0f0,5px 5px 10px 30px #f00;}
实现的效果是:
阴影并不改变元素盒模型的大小,但是可以超出其盒界限。
一些盒模型阴影的例子>> (请使用-webkit内核浏览器打开,如Safari、Chrome)
由于CSS3大多数属性的规范目前还处于制定、草案或者投票阶段,各个浏览器目前都是按自己的方式在实现这些属性,实际应用时这些属性也要加上浏览器前缀,比如在Safari和Chrome、Mobile Safari和Android Browser中使用box-shadow属性时,我们实际使用的属性名称是-webkit-box-shadow,Firefox 4.0之前使用这个属性必须使用moz-前缀,即moz-box-shadow。
顺便说一点,阴影只能根据元素盒模型的形状来投影,而不会根据里面的内容投影。比如,我们放一张兔子形状、背景透明的PNG图片在页面里,按Photoshop的思路,我们想它能投出一个兔子形状的阴影,像这样:
而实际上,在页面里CSS只能根据这张图片的形状投影:因为图片是矩形,阴影也只能是矩形。比如,我们这样定义
img{
-webkit-box-shadow:5px 5px 20px 30px #000;
-moz-box-shadow:0 0 #000;
margin-bottom:50px;
}
img{
-webkit-box-shadow:5px 5px 20px 30px #000;
-moz-box-shadow:0 0 #000;
margin-bottom:50px;
}
在页面是行呈现的投影的结果是这样:
如果我们改变了盒模型的形状,比如,我们给上面这张图片定义了圆角,使它成为一个圆形,那么我们也可以得到一个圆形的阴影,如下图——这都是盒模型的形状,你不能指望光线能穿过透明的部分,去呈现一个兔子的阴影出来。
img{
-webkit-box-shadow:5px 5px 20px 30px #000;
-moz-box-shadow:0 0 #000;
-webkit-border-radius:100px;
-moz-border-radius:100px;
margin-bottom:50px;
}
img{
-webkit-box-shadow:5px 5px 20px 30px #000;
-moz-box-shadow:0 0 #000;
-webkit-border-radius:100px;
-moz-border-radius:100px;
margin-bottom:50px;
}
2、文字阴影
W3C关于文字阴影的定义放在<CSS3文字模块>(CSS3 Text Module),也是候选推荐标准——从2003年开始就是这个状态了,这可能是W3C最早开始定义的CSS3模块,因此在各浏览器中使用这个属性时,不需要加浏览器前缀,可以直接使用text-shadow。
[<color> <length> <length> <length>? | <length> <length> <length>? <color>?]
文字阴影原理和盒阴影一致,不同之处是文字阴影没有扩展和内阴影属性,但有模糊半径和多重阴影累加。水平和竖直方向的偏移量必须定义,色值和模糊半径可选。
h1{
text-shadow:5px 8px 5px rgba(10, 100, 200,0.4);
font-size:60px;
font-family:Helvetica,"Microsoft YaHei";}
h1 + p{
text-shadow:1px 3px rgba(0,0,255,0.2);
font-family:Helvetica,"Microsoft YaHei";
font-size:18px;
line-height:200%;}
h1{
text-shadow:5px 8px 5px rgba(10, 100, 200,0.4);
font-size:60px;
font-family:Helvetica,"Microsoft YaHei";}
h1 + p{
text-shadow:1px 3px rgba(0,0,255,0.2);
font-family:Helvetica,"Microsoft YaHei";
font-size:18px;
line-height:200%;}
三、从Photoshop到CSS3的转换
了解了Photoshop的投影属性和CSS3的阴影属性,再来实现设计稿中的阴影效果是不是就很容易啦?经验告诉我们,理想是美好的,现实是残酷的。
我们经常会在设计稿上看到一些很美的阴影设计,比如这个导航的选项卡——又是选项卡,它似乎总是我们烦恼的起源:
图中第一个“最新动态”的白色选中项,左右有投影——我们可以认为这个选项卡的投影有3、5像素扩张,上边没有投影——并且投影向下偏移了几像素,而下方的投影被白色内容区域(就是有钉书针那块)覆盖了。如果这样写一个阴影,当然是很快就能大功告成!可是等等,我们注意到下方白色内容区域自己也带着投影,如果它覆盖了上边白选项卡的下投影,那它应该摞在选项卡的上面,可是我们并没有看到它自己的投影落在选项卡上,这是怎么回事呢?
让我们看看设计稿是怎么实现的:
上图红框内的最新动态是白色选项卡—白色背景没有任何图层属性,就是说它根本没有阴影。实际上,这里的投影是由红框内的“投影”图层实现的——它也没有阴影属性,它是个模仿投影的半透明灰色图层。在顺序上是投影层在最下面,上面摞着内容——纸,再上面是白选项卡。
好了,现在肿么办呢?难道我们要为每个选项卡准备两个标签?一个做选项卡,一个模拟选项卡下面的投影?Oh,no,那太复杂了。。我们还是希望用正确的属性做它应该做的事,比如按原来的思路做选项卡投影,再做一个东西挡住下方的投影,让选项卡跟白色内容区域无缝衔接?这时,我们想到另外一个CSS属性——伪元素:before。::befroe和它兄弟::after是最近很流行的用法,类似于把一个钱掰两半花,他们的存在能把一个元素分成三层,实现原来不能在一个对象上实现的装饰效果,具体用法在这里就不专门讲了,我们主要讲如何用它来完成选项卡的阴影效果。
首先,去掉那个模拟投影的图层,给选项卡图层定义一个真正的投影。对照原有阴影效果我们设置图层投影属性:
根据属性计算投影的左右偏移:
X = -cosθ * D = -cos90° * 4px = 0,
上下偏移:
Y= sinθ * D = sin90° * 4px = 4px
其次,设置选项卡对象的CSS属性。对应上面Photoshop的设置和计算结果,CSS阴影属性box-shadow{ inset? && [ <length>{2,4} && <color>? ] }各项取值分别为:
外阴影,不用inset参数;
length1 = 0 —— 横向偏移为0;
lengt2 = 4px —— 阴影向下偏移4px;
length3 = 10px (通过调整Photoshop的扩展属性测量出的模糊范围为10px)
length4 = 9px-5px (由于模糊半径向外扩张了5px,为保持阴影范围不超过,将扩张缩小5px)
color=rgba(0,0,0,0.25) —— 原阴影图层颜色为黑色,透明度25%
CSS代码:
nav li a{
-webkit-box-shadow: 0 4px 10px 4px rgba(0, 0, 0, 0.25);
-moz-box-shadow: 0 4px 10px 4px rgba(0, 0, 0, 0.25);
background: #F8F8F8;
color: #4D4D4D;
font-size: 15px;
line-height: 47px;
position: absolute;
top: -2px;
width: 100%;
z-index: 8;
}
nav li a{
-webkit-box-shadow: 0 4px 10px 4px rgba(0, 0, 0, 0.25);
-moz-box-shadow: 0 4px 10px 4px rgba(0, 0, 0, 0.25);
background: #F8F8F8;
color: #4D4D4D;
font-size: 15px;
line-height: 47px;
position: absolute;
top: -2px;
width: 100%;
z-index: 8;
}
还要做一块遮住下阴影的补丁,补丁的宽、高能遮住下阴影即可:
nav li a.on::before{
position:absolute;
content:"" ;
background:#ffffff;
width:120%;
height: 22px;
bottom:-20px;
left:-10%; }
nav li a.on::before{
position:absolute;
content:"" ;
background:#ffffff;
width:120%;
height: 22px;
bottom:-20px;
left:-10%; }
html代码:
<nav class="nav-myspace">
<ul>
<li class="on"><a href="myspace_minifeed.html">最新动态</a></li>
<li><a href="myspace_shuoshuo.html">说说</a></li>
<li><a href="myspace_blog.html">日志</a></li>
<li><a href="myspace_album.html">相册</a></li>
<li><a href="myspace_message.html">留言板</a></li>
</ul>
</nav>
<nav class="nav-myspace">
<ul>
<li class="on"><a href="myspace_minifeed.html">最新动态</a></li>
<li><a href="myspace_shuoshuo.html">说说</a></li>
<li><a href="myspace_blog.html">日志</a></li>
<li><a href="myspace_album.html">相册</a></li>
<li><a href="myspace_message.html">留言板</a></li>
</ul>
</nav>
最后效果:
好吧,它还不尽善尽美,这就是模糊半径的后遗症。
Ok,这就是一个阴影实际应用的例子,它告诉我们:木有使用Photoshop投影属性的阴影,对制作经理来说,实现设计仍然是一件不容易的事,所以,即使设计师在设计时采用其他方式模拟阴影,也应该标出模拟阴影的角度、距离、大小、扩展这几个属性。这对准确实现阴影效果是很重要的——不然就只能跟着感觉走了。
四、浏览器的支持
浏览器们对box-shadow和text-shadow的支持也是逐步完善的,例如,从Safari3.0开始支持基本的阴影属性(水平、垂直方向的偏移、模糊半径),到Safari 5.0才开始支持inset和模糊半径参数,Mobile Safari到3.0开始支持。而Android Browser 2.1以下如果定义了inset属性,会引起阴影属性失效。
浏览器对这两个属性的支持情况如下:
总结下来,Photoshop中投影的颜色、透明度、角度、距离、大小属性都可以准确转换为CSS3中的盒阴影属性,但是扩展属性换算成CSS模糊半径不能精确,并且会影响其他属性,使用时要根据实际情况微调。