最近的项目中遇到了这个问题,背景颜色半透明效果的需求。以前只是知道使用alpha通道和opacity来实现透明,这次发现问题并不是这么简单的,背景色透明了,但是文字也跟随透明了!所以做了一下研究,总结出来各浏览器的差异和文字不透明处理,文章最后提出了建议采用的方法。

一、使用rgba()样式

问题发生在这样的文档结构上:

<div class="inner">
     <p>文字</p>
</div>

div.inner使用半透明背景,文字p为白色。一般情况下,我们会这样来处理样式:

.inner {
    background-color: rgba(0, 0, 0, 0.5);
}
.inner p {
    color: #fff;
}

这样写在支持CSS3的浏览器中没有压力,但是在IE8及以下这样写就实现不了效果了。

IE6、IE7和IE8不支持rgb()中的alpha通道,rgba()他们不认识就不解析,所以背景是全透明的,没有达到预期效果。

IE9 FireFox Chrome Safari Opera

IE6 IE7 IE8

![rgba()在支持CSS3的浏览器中实现背景色半透明](/uploads/2012/04/image_thumb5.png "rgba()在支持CSS3的浏览器中实现背景色半透明") ![rgba()在不支持CSS3的浏览器中效果](/uploads/2012/04/image_thumb6.png "rgba()在不支持CSS3的浏览器中效果")
可以看到,支持rgba()的浏览器半透明效果很好!背景透明了,子节点的文字依然不透明。

二、使用rgb()和opacity

同样的结构,我们换个样式,使用rgb()和opacity,因为IE8及以下不支持opacity,因此使用filter属性。filter属性在非IE浏览器下均不能识别。

.inner {
    background-color: rgb(0, 0, 0);
    opacity: 0.5;               /*IE9 FF Chrome Opera*/
    filter: alpha(opacity=50);  /*IE*/
    *zoom: 1;                   /*IE7下激发hasLayout*/
}
.inner p {
    color: #fff;
}

这样的做法就能支持大部分的浏览器了,除了IE6。

FireFox Chrome Safari Opera IE9 IE8 IE7

IE6
![rgb()和opacity实现背景色半透明](/uploads/2012/04/image_thumb7.png "rgb()和opacity实现背景色半透明") ![IE6不支持opacity和filter](/uploads/2012/04/image_thumb8.png "IE6不支持opacity和filter")
可以看到,背景虽然是透明了,但是文字也跟随着透明了。这样的情况在IE8及以下比较好解决,反而比较标准的浏览器就不好解决了。

注:在IE9中opacity和filter它都能解析,如果两个同时存在,则以透明度较低即数字较大的为准,不会叠加。例如:filter:alpha(opacity=80);opacity:0.5;它会以80%的透明度来解析。

在IE8和IE7中对文字的节点添加“position: relative;”样式就能实现文字不透明了。

.inner p {
    color: #fff;
    position: relative;
}

效果图:

IE7和IE8使用position:relative实现文字不透明

三、总结

在文档结构不能修改的情况下,遇到这样的问题我们可以这样解决。

  1. 对支持CSS3的浏览器使用rgba()来实现;
  2. 对IE8和IE7使用rgb()、opacity和position:relative来实现;
  3. 对于IE6可以使用1像素图片repeat来实现。
    而我们往往希望使用一套代码简洁的来实现这样的效果,下面我想到两个方案来实践:
方案一:使用图片来替代。

如果你的站点打算兼容IE6而且这样的使用范围广的话,那毫不犹豫的使用上面说到的使用图片,并且在IE6下需要对图片加上IE滤镜,这样做的同时对这张1像素图片进行做data-uri转码,直接写进样式表中。不过滤镜只能使用在背景图为no-repeat的情况下,所以,完美的做法需要加上js来使它透明化。

.inner {
    background: url(alpha-bg/alpha-bg-50.png) repeat;
}

js脚本处理,这里使用了jQuery和fixPNG()方法。

<!--[if IE 6]>
    <script type="text/javascript" src="alpha-bg/jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="alpha-bg/ie6_png_patch.js"></script>
    <script type="text/javascript">$('.inner').fixPNG();</script>
<![endif]-->
方案二:不使用图片,舍弃IE6。

如果你的站点不打算兼容IE6,在IE6下背景色全黑影响不大的话,我们考虑使用hack。

同时将上面说到的第1点和第2点同时写进样式表,这样做的会产生一个问题。在IE9中,它既支持opacity又同时支持filter!所以这样在IE9下变得非常的透明!因为它在rgba()中已经半透明了,解析到filter或者opacity属性时又再透明一次,做了叠加!

所以可以这样写:

.inner {
    /*IE*/
    background-color: rgb(0, 0, 0);
    filter: alpha(opacity=50);
    *zoom: 1;
    /*NO-IE*/
    background-color: rgba(0, 0, 0, .5);
    /*IE9*/
    background-color: #0009;
}
.inner p {
    position: relative;
}

上面的样式表中使用了IE9特有的hack标记”9”,使背景色被黑色覆盖。

注:注意上面属性的抒写顺序,且只能使用16进制表示颜色,不能使用rgb()。

方案三、洁癖方案。

这个方案综合了方案一和方案二,使各浏览器下的效果都一致。

css可以这样写:

.inner {
    /*IE*/
    background-color: rgb(0, 0, 0);
    filter: alpha(opacity=50);
    *zoom: 1;
    /*NO-IE*/
    background-color: rgba(0, 0, 0, .5);
    /*IE9*/
    background-color: #0009;
    _background: url(alpha-bg/alpha-bg-50.png) repeat;
}
.inner p {
    position: relative;
}

在使用bootstrap框架中,less可以这样写:

.css-background-transparent(@color: #000, @opacity: 50) {
    /*IE*/
    background-color: @color;
    filter: ~"alpha(opacity=@{opacity})";
    *zoom: 1;
    /*NO-IE*/
    #translucent>.background(@color, @opacity / 100);
    /*IE9*/
    background-color: ~"@{color} 9";
    /*IE6*/
    _background: url("alpha-bg/alpha-bg-@{opacity}.png") repeat;
}

四、测试环境和页面

查看测试页面:css-background-transparent.html

<!DOCTYPE HTML>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta name="Author" content="mumu mumu@imozo.cn">
    <title>主流浏览器下背景色半透明的兼容性</title>
    <style type="text/css">
        .rgba,
        .rgb,
        .scheme-one,
        .scheme-two,
        .scheme-three {
            width: 400px;
            background: url(alpha-bg/bg.jpg) 0 -80px no-repeat;
        }
        p {
            margin: 1em 0;
            text-align: center;
        }
        .inner {
            margin: 0 15px;
            padding: 10px;
            color: #fff;
        }
        .inner p.relative {
            position: relative;/*IE7、8下文字不透明处理*/
        }
        /*rgba*/
        .rgba .inner {
            background-color: rgba(0, 0, 0, .5);
        }
        /*rgb*/
        .rgb .inner {
            background-color: rgb(0, 0, 0);
            opacity: .5;
            filter: alpha(opacity=50);/*IE*/
            *zoom: 1;
        }
        /*scheme-one*/
        .scheme-one .inner {
            background: url(alpha-bg/alpha-bg-50.png) repeat;
        }
        /*scheme-two*/
        .scheme-two .inner {
            /*IE*/
            background-color: rgb(0, 0, 0);
            filter: alpha(opacity=50);
            *zoom: 1;
            /*NO-IE*/
            background-color: rgba(0, 0, 0, .5);
            background-color: #0009;
        }
        /*scheme-three*/
        .scheme-three .inner {
            /*IE*/
            background-color: rgb(0, 0, 0);
            filter: alpha(opacity=50);
            *zoom: 1;
            /*NO-IE*/
            background-color: rgba(0, 0, 0, .5);
            background-color: #0009;
            _background: url(alpha-bg/alpha-bg-50.png) repeat;
            _filter: alpha(opacity=100);
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="header">
            <h1>主流浏览器下背景色半透明的兼容性</h1>
        </div>
        <div class="main">
            <h2>1、使用rgba(0,0,0,0.5)实现</h2>
            <div class="rgba">
                <div class="inner">
                    <p>使用rgba来定义背景色</p>
                    <p>使用rgba来定义背景色</p>
                    <p>使用rgba来定义背景色</p>
                    <p>使用rgba来定义背景色</p>
                    <p>使用rgba来定义背景色</p>
                </div>
            </div>
            <h2>2、使用rgb(0,0,0)和opacity:0.5实现</h2>
            <div class="rgb">
                <div class="inner">
                    <p class="relative">使用rgb来定义背景色,使用了relative</p>
                    <p class="relative">使用rgb来定义背景色,使用了relative</p>
                    <p class="no-relative">使用rgb来定义背景色,没有使用relative</p>
                    <p class="no-relative">使用rgb来定义背景色,没有使用relative</p>
                    <p class="no-relative">使用rgb来定义背景色,没有使用relative</p>
                </div>
            </div>
            <h2>3、方案一:使用图片替代</h2>
            <div class="scheme-one">
                <div class="inner">
                    <p>使用图片</p>
                    <p>使用图片</p>
                    <p>使用图片</p>
                    <p>使用图片</p>
                    <p>使用图片</p>
                </div>
            </div>
            <h2>4、方案二:不使用图片,舍弃IE6</h2>
            <div class="scheme-two">
                <div class="inner">
                    <p class="relative">不使用图片,舍弃IE6</p>
                    <p class="relative">不使用图片,舍弃IE6</p>
                    <p class="relative">不使用图片,舍弃IE6</p>
                    <p class="relative">不使用图片,舍弃IE6</p>
                    <p class="relative">不使用图片,舍弃IE6</p>
                </div>
            </div>
            <h2>5、方案三:洁癖方案</h2>
            <div class="scheme-three">
                <div class="inner">
                    <p class="relative">各浏览器效果均一致</p>
                    <p class="relative">各浏览器效果均一致</p>
                    <p class="relative">各浏览器效果均一致</p>
                    <p class="relative">各浏览器效果均一致</p>
                    <p class="relative">各浏览器效果均一致</p>
                </div>
            </div>
        </div>
        <div class="footer">

        </div>
    </div>
    <!--[if IE 6]>
 <script type="text/javascript" src="alpha-bg/jquery-1.7.1.min.js"></script>
 <script type="text/javascript" src="alpha-bg/ie6_png_patch.js"></script>
 <script type="text/javascript">$('.scheme-one .inner').fixPNG();$('.scheme-three .inner').fixPNG();</script>
 <![endif]-->
</body>
</html>

测试环境:

操作系统版本:
Windows 7 Ultimate build 7600

浏览器版本:
IE6
IE7
IE8
IE9
Firefox 11.0
Chrome 16.0.912.75
Safari 5.1.5(7534.55.3)
Opera 11.62

测试页面:css-background-transparent.html