用 CSS 实现的阴影效果
原文出自:A List Apart 作者:Sergio Villarreal
中文翻译:onestab [2004.02.28]
阴影效果成了平面设计的一个套路,平面设计师把它当作瑞士军刀的起子,随处使用,尽管招致不少非议,却一直广受欢迎。虽然用图像编辑软件也能实现阴影效果,但在Web设计快速发展的今天,适应性和易用性是大势所趋,这种以固定背景效果制作出的静态图片很难有良好的适应性。
假如有一种技术,用 CSS 对任意块级元素灵活地添加阴影,而且能随着内容的大小自动扩展,还要适用于大多数流行的浏览器,那该有多好!不信么?告诉您,只需写几行代码就能做到。
是不是很有意思?先别急,这可不是我们的发明,我们只不过对此作了改进。这个技术是由著名的 1976 design 上的 Dunstan Orchard (向 Dunstan 脱帽致敬)构思出来的,并且作了演示。我们觉得这个方法简洁实用,但深入研究之后,发现还有改进的余地。
这里是它的工作原理:先用图像软件制作一幅背景图片,图片上只有阴影,不能有可见的边界(一种简便的方法是对空白的选择区域应用某种效果)。这个图片要能够覆盖将要修饰的最大元素,实践当中,800 x 600 一般就足够了。将它保存为GIF图片,记住一定要在背景颜色之上应用效果,此外再把它另存为完全透明的PNG图片(即没有背景色)。这是为了根据浏览器的能力区别对待[译注:即让支持透明 PNG 图片的浏览器使用PNG,IE 使用GIF。]。这里是将要用到的 GIF 文件以及 PNG 文件。
我们先从如何为图片添加阴影开始,然后再扩展到其他块级元素。为了直观起见,我们把这个 class 命名为 img-shadow,我们先用这只可爱的小猫作个试验:
相应的代码(只需额外增加一个 div ):
<div class="img-shadow"> <img src="cat.jpg" alt="test"/> </div>
下图演示了我们所用到的技术:
首先,我们用先前准备的阴影图片作为该 div 的背景。
background: url(shadow.gif) no-repeat bottom right;
然后,我们将图片的左边距和上边距设为负值,使它“投下”阴影,阴影的宽度为 6 个像素,也就代码中的数字:
margin: -6px 6px 6px -6px;
为避免指定该 div
的大小,我们将它浮动起来。(否则它将占据全部可用的水平空间。)
还记得前面我们说过,要让好的浏览器显示好的阴影效果吗?诀窍在这行代码:
background: url(shadowAlpha.png) no-repeat right bottom !important;
这里的“!important”表示此处指定的样式的优先级高于同元素上的普通样式声明(参见 标准),对透明 PNG 缺乏内在支持的所有版本的 Internet Explorer 刚好也不支持“!importan”。通过互相矛盾的两次声明,我们得到了期望的结果(IE 用的是第二个,而大多数浏览器会采用第一个)。最终的结果是这样的:当需要改变背景颜色时,支持 PNG 的浏览器显示出的阴影效果非常完美。而在可怜的 IE 中,阴影还是它原来的颜色。
你可能会问,为什么要这样做?答案是可以一箭双雕。
- 我们能够: 不费吹灰之力就可以自动地让高级的浏览器发挥它的最好效果。
- 它能自我修复: 如果(随Longhorn而来的)新版 Internet Explorer 支持这两个标准,我们无须进行修补,仍然能够获得精确、完全透明的阴影。
最终的 CSS 代码是这样的:
.img-shadow { float:left; background: url(shadowAlpha.png) no-repeat bottom right !important; background: url(shadow.gif) no-repeat bottom right; margin: 10px 0 0 10px !important; margin: 10px 0 0 5px; } .img-shadow img { display: block; position: relative; background-color: #fff; border: 1px solid #a9a9a9; margin: -6px 6px 6px -6px; padding: 4px; }
为了补偿 IE 浮动模型的错误,所以上面代码中的 margin 有些差异,而最后一行的 padding 将图片框装扮得更加漂亮,可惜在 IE 5.0 和 5.5 中不起作用,不过阴影效果仍然存在。
在符合标准的浏览器中,阴影和背景无缝融合在一起。在 IE 中,除非你把阴影和背景设为同一颜色,否则阴影和背景的过渡就显得比较生硬。这里就是最终效果:[译注:请在不同的浏览器中观看效果。]
接下来让我们为一段文字加上阴影效果。
一段文字只不过是一个区块元素,按理说上面的技术应该同样适用。实际上,在大多数浏览器中都没问题,猜猜看,到底是哪个浏览器搞的破坏?
在开发这种技术时,我们发现如果要应付的不是图片,而是一个块级元素,则难度之大超出了我们的想象。不管我们如何尝试,IE 总是把左上角(也就是“突出”阴影之外的部分)给切掉。更可笑的是,只有 5.0 版的 IE 表现正常。看来任何技巧、溢出设定或者建议都于事无补(当然也试过念咒语)。我们决定放弃,转而寻求别的解决方案。
我们先从 Douglas Bowman 的Sliding Doors(滑门)方法开始,当然额外的开销(另一个 div)必须要有,我们的这个段落应该是这个样子:
<div class="p-shadow"> <div> <p>The rain in Spain ...</p> </div> </div>
与刚才指定负的左、上边距(margin)值的做法相反,这回我们为右、下边距(padding)指定正值,将阴影(其实是外层 div 的背景)暴露出来。然后,我们用一个局部透明的 GIF 图片放在阴影之上,伪造出假的阴影偏移效果。注意,图片可见部分的颜色要与用于阴影效果的背景颜色相同。这幅图片的名字为 “shadow2.gif”。图片的构成如下:
这就是GIF 图片的例子(这幅图片在浏览器的中看起来好像是空白的,所以最好把它存起来,在图形处理软件中观看。)
这就是我们想要达到的效果:
下面是实现这种效果的样式表。注意额外的图片和补白(padding)仅仅用于 Internet Explorer。绝大多数浏览器会忽略内层的 div,仍然使用前面讲过的图片阴影效果技术。
.p-shadow { width: 90%; float:left; background: url(shadowAlpha.png) no-repeat bottom right !important; background: url(shadow.gif) no-repeat bottom right; margin: 10px 0 0 10px !important; margin: 10px 0 0 5px; } .p-shadow div { background: none !important; background: url(shadow2.gif) no-repeat left top; padding: 0 !important; padding: 0 6px 6px 0; } .p-shadow p { color: #777; background-color: #fff; font: italic 1em georgia, serif; border: 1px solid #a9a9a9; padding: 4px; margin: -6px 6px 6px -6px !important; margin: 0; }
在前面的图片例子中提到的背景色注意事项,段落也应加以注意。这就是最终的效果。(请试着改变浏览器窗口大小,观察段落大小的改变和阴影的调整。)
The rain in Spain falls mainly on the plain. The rain in Spain falls mainly on the plain. The rain in Spain falls mainly on the plain.
附注
本文为了清楚起见,将图片和段落的样式打散了,但其实可以做些小小的更改,将它们整合在一起。
这个技术已经在 Gecko 引擎的浏览器、Safari、Opera 和 IE 5.0+ 中 测试过,除了提到的一些微小的差异,还没有发现什么问题。应当适用于大多数的浏览器(除了 Netscape 4.x)。
致谢
感谢发明了阴影技术的 Dunstan,以及 Douglas Bowman 的 Sliding Doors 技术。