2011.10 12

背景半透明最佳实践

透明作为一种效果增强的方案,被众多视觉设计师喜欢。但因为 IE 的原因,透明,特别是半透明,已经成为前端工程师最不愿意实现的东西。现在有一个需求,需要对一个纯色的层实现半透明效果。效果如下,边框需要透明,透明度为 #000000 的 30%:

背景半透明

用各种浏览器打开下面这个 DEMO, IE9 有特殊显示:

DEMO: 背景半透明最佳实践 »

一、使用 opacity + Alpha Filter

看起来手挺简单的吧?嗯。挺简单的… 希望你能很方便实现这个方案!其实见到这个的时候,我们的第一想法当然是 background + opacity,在不支持 opacity 的 IE 使用 filter 的 alpha 滤镜来实现。然后,我们得到这样的效果:

背景半透明

.opacity{
    background:#000;
    opacity:0.3;
    filter: alpha(opacity=30);
}

无一例外,最外层,最内层和文字,都被设置了 opacity(alpha 也是使用 opacity ) 。当然,我们可以给各层设置 opacity 变回来。但这是多麻烦的事(不信试一下)。

二、最佳实践:rgba色彩 + Gradient Filter

其实我们可以选用 background-color: rgba() 来实现,同样可以实现透明效果,并且只应用于当前元素,不继承。而 IE 的 filter 有很多滤镜效果。其中的渐变滤镜,只要变通一下,就可以实现我们想要的效果,并且这个滤镜不会被下级元素继承,这样元素的内容就不会被虚化。代码如下:

/*
 * filter 渐变滤镜详细用法,[参见这里]
 * StartColorStr 和 EndColorStr:
 *    #4c000000 是 30% 透明度的 #000000 的意思
 *    组成: # + 透明度 + 颜色
 *    算法: Math.floor(0.6 * 255).toString(16);
 */
.rgba{
    background:rgba(0, 0, 0, 0.3);
    filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#4c000000', EndColorStr='#4c000000');
}

 不过,我们得到的效果是这样的,IE9 的透明度竟然有 60%!! 这显然不是我们想法的。原因是:IE9 也支持 filter,使得 filter 的结果和 background-color 叠加,所以是 60%。具体参见 DEMO 和示例图:

背景半透明

那么我们可以利用 IE 的 HACK,单独把 IE9 的 filter 变成透明度为 0 即可。高级浏览器大部分支持 :root 伪类,但不支持 filter 属性,而 IE 只有 IE9 支持,所以我们可以这样写。代码如下:

:root .rgba{
    filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#00000000', EndColorStr='#00000000');
}

 当然,第二种方法可以应用于 background,也可应用于 border 上。整体的代码可参见 DEMO。最后,还是那句话,期待你更好的解决方案。

参考文献:

41

  1. 2011.10.12 2:16 pm
    ray(visit): [回复]

    我又来了。opacity原来是继承的啊。

  2. 2011.10.12 2:16 pm
    Kimcool(visit): [回复]

    我个人不是很喜欢透明,还是比较喜欢一个白底的。。

  3. 2011.10.12 2:39 pm
    (visit): [回复]

    学习了,虽然滤镜不会用……

  4. 2011.10.12 2:53 pm
    wheato(visit): [回复]

    学习了,以后有项目需要的时候就能使用了。

  5. 2011.10.12 3:42 pm
    w-school(visit): [回复]

    一直使用第一种方法,没研究这么细,如果一张图片的标题背景透明浮动于图片之上,不用定位用margin-top负值,透明的标题背景用background:rgba(0, 0, 0, 0.3);实现,则标题背景会跑到图片下面,opacity:0.3;则不会

  6. 2011.10.12 3:49 pm
    夜色倾城(visit): [回复]

    不是做这行的,平常自己做主题,就直接RGBA了,不兼容就不兼容吧,既然用IE,看不到炫丽的效果也不能怪我了,世界变化你不变,享受不到新科技的好处,这只能怪你自己。

  7. 2011.10.12 4:42 pm
    愚人码头(visit): [回复]

    提供一个背景色透明的颜色转换工具:http://www.css88.com/demo/hex_color/

  8. 2011.10.12 5:43 pm
    ktmud(visit): [回复]

    直接 :root .rgba { filter: none } 啊

  9. 2011.10.12 10:30 pm
    峰子(visit): [回复]

    实际上,rgba我在做一个主题的时候就已经使用,但是并不兼容ie,在ie没有找到很好的解决方法,所以决定在ie不半透明。原来还有一个滤镜,确实不错。

  10. 2011.10.13 9:59 am
    Alan(visit): [回复]

    之前就是弄一个空div做背景透明,然后再把内容叠上去,这个方法必须得挺啊

  11. 2011.10.13 12:32 pm
    linxz(visit): [回复]

    @愚人码头: 我勒个擦,码头,出错信息没填好~~~

  12. 2011.10.13 12:33 pm
    linxz(visit): [回复]

    小鱼,如果可以话,用半透明的PNG24图也是一种方法,IE6用滤镜,滤镜有一个属性我记得好像是拉伸(如果没记错的话),那么也就可以实现自适应了。嘻嘻。

    不过最好的办法应该是差异化,不支持RGBA的就不透明。

  13. 2011.10.13 12:34 pm
    愚人码头(visit): [回复]

    @linxz: 昨天我本来想把出错信息给直接咔嚓掉的,一个小工具还要什么出错提示啊!

  14. 2011.10.13 1:12 pm
    sofish(visit): [回复]

    @linxz: scale 确实可以拉升… 这是一个不错的方案。只是要增加一张图片和浏览器对图片拉伸产生的内存消耗会带来更多的性能下降

  15. 2011.10.13 3:33 pm
    linxz(visit): [回复]

    @愚人码头: 小工具为什么就不能有提示呢,给用户一个好的体验嘛,嘻嘻。

  16. 2011.10.13 3:34 pm
    linxz(visit): [回复]

    @sofish: 鱼和熊掌不可兼得啊,使用滤镜的时候其实已经在消耗资源了,所以干脆就分级策略,让低端浏览器不透明吧。

  17. 2011.10.13 5:22 pm
    sofish(visit): [回复]

    @linxz: 一直很喜欢降级处理这种方式。但交互都比较苦逼,太难说服了

  18. 2011.10.14 5:53 am
    软件志(visit): [回复]

    半透明的东东视觉效果不错

  19. 2011.10.16 10:26 pm
    Rainbow(visit): [回复]

    优雅降级,非常好的思想,就是有的时候还是被苦逼了,剩下的就是悲剧了!

  20. 2011.10.17 11:17 am
    lxliori(visit): [回复]

    已经用到项目中,感谢分享

  21. 2011.10.17 5:13 pm
    付正宗(visit): [回复]

    opacity指的是不透明度,楼主理解有误,鉴定完毕~

  22. 2011.10.21 12:47 am
    wmtimes(visit): [回复]

    图片吧。再加js

  23. 2011.10.21 11:27 am
    hsinglin(visit): [回复]

    刚好项目用到了~~哈哈~~

  24. 2011.10.23 10:13 pm
    峰子(visit): [回复]

    滤镜后加上这句就ok:background:none9;

  25. 2011.11.03 10:23 am
    胡尐睿丶(visit): [回复]

    @ray: 而且是强制继承,无法解除

  26. 2011.11.09 3:21 am
    宝宝健康成长(visit): [回复]

    又没有ie6啥事,该杀的

  27. 2011.11.11 6:35 pm
    袁源(visit): [回复]

    一般遇到的都是 png-24 图片的半透明

  28. 2011.11.23 9:56 am
    Joe(visit): [回复]

    话说透明层如果设置了background属性的话,在IE7、6 rgba透明会失效。

  29. 2011.11.29 9:16 pm
    wyysf(visit): [回复]

    我做的有个项目就有个类似的,主要是高度还要自适应,所以多写个层定位不靠谱了,最后我才用的还楼主的方法相同,郁闷的是最后他们把它还给去掉了!唉~~~

  30. 2011.12.07 11:52 pm
    watert(visit): [回复]

    事实上在这方面有个CSS3工具简直是神器,不过可惜文字和BOX阴影、圆角貌似仍然没有很好的解决方案(阴影问题似乎可以用HTA+VML实现,但我引入到实际项目中时总会出问题……)
    http://www.colorzilla.com/gradient-editor/

  31. 2011.12.21 12:55 pm
    海六(visit): [回复]

    很牛的博客!

  32. 2011.12.26 2:29 pm
    vimest(visit): [回复]

    两种滤镜在ie上还是有区别的。
    如常见的弹出框,弹出后其它区域变为黑色透明,如果这个黑色透明的元素用opacity和opacity滤镜来写,除了会影响后代元素外就没什么大的问题了。
    但如果用背景rgba的和rgba滤镜写的话,虽说不会影响后代元素,但在ie678下却有个bug,就是被遮住的链接,能选择,hover的时候有变化,点击后还能跳转。
    具体看这demo:
    http://vimest.github.com/ieFilter.html

  33. 2011.12.29 10:08 am
    cougar(visit): [回复]

    如果不想用滤镜,可不可以用png+dd_belatedPNG实现,不过这个方法比滤镜麻烦些。

  34. 2012.02.03 3:16 pm
    耗子(visit): [回复]

    @cougar: belatedPNG底层还是很耗性能的vml

  35. 2012.02.20 10:23 am
    312166304(visit): [回复]

    ie下给子元素添加relative就可以

  36. 2012.02.29 10:51 am
    qiqiboy(visit): [回复]

    所谓最佳实践还是太麻烦了些,代码又多,我会用一个绝对定位的空div作为背景,设置半透明,这样就行了,绝对兼容各个浏览器,也没有图片。。

  37. 2012.08.30 6:00 am
    diva(visit): [回复]

    嘿嘿,一直用码头的这个小工具。。很好。

  38. 2012.11.03 4:04 pm
    吖坚(visit): [回复]

    可以加一句:background-image:url(about:blank)

  39. 2012.12.17 3:48 am
    wenbin(visit): [回复]

    不错,之前都没注意ie9会重叠

  40. 2013.04.24 5:47 am
    Ygs(visit): [回复]

    如果用JS呢?

  41. 2013.05.06 2:54 pm
    昔影(visit): [回复]

    ie下用滤镜要无背景色,那么再加绝对定位有层叠的话,光标是可以穿透层的。