背景半透明最佳实践

透明作为一种效果增强的方案,被众多视觉设计师喜欢。但因为 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。最后,还是那句话,期待你更好的解决方案。

参考文献:

47 thoughts on “背景半透明最佳实践

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

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

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

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

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

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

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

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

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

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

  9. 你好,你说:当然,我们可以给各层设置 opacity 变回来。但这是多麻烦的事(不信试一下)。

    我的理解是,html结构不改变,直接给各层设置opacity的话,是变不回来的!已在ff和chrome实践过。具体原因可看https://developer.mozilla.org/en-US/docs/Web/CSS/opacity这里有写到:
    The value applies to the element as a whole, including its contents, even though the value is not inherited by child elements. Thus, an element and its contained children all have the same opacity relative to the element’s background, even if the element and its children have different opacities relative to one another.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>