• 关于opacity透明度子元素继承现象的若干研究以及hack方法


    【感想】信息时代的信息是有时效性的,今天是确确实实感受到了。互联网资料虽然丰富,但是质量不一,还有大量的跟风雷同,很多人都是随手拷贝过来,根本没有实践。以前端为例,这两年浏览器的迅猛发展,造成很多原有知识的失效。但是网上还是大量充斥了以前失效的解决方案。我觉得,我们应本着实践精神,对任何问题的解决方案进行实际测试。须知:纸上得来终觉浅,绝知此事要躬行。

    今天遇到一个关于透明度的问题。

    大家都知道在css3中增加的新属性opacity——不透明度的设定。

    使用了opacity的元素,它的不透明度会被子元素继承。例如:1_demo.html

    代码如下:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title></title>
        <style type="text/css">
        body{ background-color: #000; }
        .a{ width: 200px; height: 150px; background-color: #37a7d7; color: #fff; }
        .opacity{ filter:alpha(opacity=50); /*for IE*/opacity: 0.5;/*非IE*/ }
        </style>
    </head>
    <body>
        <div class="a">我是b-DIV</div>
        <div class="a opacity">我是b-DIV</div>
    </body>
    </html>

    效果如下:

    image

    可以看出,不光b-DIV本身透明度改变了,他的子元素的透明度也跟着改变了。

    有时候我们不希望子元素的透明度改变,例如上面的例子,我们不希望里面的字也变得透明。下面我们做几个实验试试。

    一、

    网上流传很广的一个方法,是给子元素在给包裹起来,然后设置position为relative或者absolute

    例如,我们更改上面例子的代码,2_demo.html

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title></title>
        <style type="text/css">
        body{ background-color: #000; }
        .a{ width: 200px; height: 150px; background-color: #37a7d7; color: #fff; }
        .opacity{ filter:alpha(opacity=50); /*for IE*/opacity: 0.5;/*非IE*/ }
        </style>
    </head>
    <body>
        <div class="a">
            <div>我是b-DIV</div>
        </div>
        <div class="a opacity">
            <div style="position:relative">我是b-DIV</div><!-- 我是新增代码 -->
        </div>
    </body>
    </html>

    firefox31下:

    image

    chrome35下:

    image

    IE9-11下:

    image

    但是在IE7、8下竟然可以:

    无标题

    老办法还真是只能对付“老浏览器”…….

    二、

    看来在firefox、chrome和IE9/10/11 下,利用position把子元素脱出文档流这种方法应该是无解了。

    那我们换个思路,直接给子元素定义opacity:1行不行。

    <div style="position:relative;opacity: 1">我是b-DIV</div>

    例子:3_demo.html

    image

    其实是这样的,如果父元素定义了opacity,那么子元素在定义一个opacity,那么子元素的效果其实是两者的乘积…

    例如,父元素的opacity:0.5,子元素opacity:0.2,那么子元素实际的opacity=0.5x0.2=0.1

    这个大家可以自己尝试下就知道了。

    设置了opacity的父元素,此属性一定会被子元素继承。

    三、

    第三种方法:使用css3的另一个属性:background-color:rgba();

    以上面的背景色 #37a7d7为例,其rgb写法为:rgb(55,167,215),两者可以等价交换。

    在css3中的rgba(),rgba(55,167,215,0.5),其中第四项0.5即为不透明度。

    例子:4_demo.html

    image

    聪明的你一定马上想到那么

    background-color:rgba(55,167,215,0.5);

    等价于

    background-color:rgb(55,167,215);opacity:0.5;

    是,也不完全是。因为对于使用rgba设置的不透明度,子元素是不会继承的。

    但是,IE7、8是不支持rgba()…..

    四、

    通过上面这些方法,我们可以看出来,子元素是必须继承父元素的opacity。那我们再换个思路,不让它成为子元素呢?例子:5_demo.html

    代码:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title></title>
        <style type="text/css">
        body{
        background-color: #000;margin: 0;padding: 0;
    }
        .noOpacity{
        width: 300px;
        height: 250px;
        background-color: #37a7d7;
        color: #fff;
    }
    /*上面的是背景对比,以下是方法*/
        .container {
        width: 300px;
        height: 250px;
        color: #fff;
        position:relative;
    }
       .content {
        position:relative;
        z-index:5;
        width: 100%;
        height: 100%;
        overflow: hidden;
    }
       .background {
        background-color: #37a7d7;
        position:absolute;
        top:0px;
        left:0px;
        width:100%;
        height:100%;
        z-index:1;
        /*兼容IE7、8 */
           -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
        filter: alpha(opacity=50);
        opacity:.5;
    }
        </style>
    </head>
    <body>
        <div class="noOpacity">我是用来作对比的</div>
        <div class="container">
            <div class="content">
                <p>我是class为content的DIV</p>
                <p>我的背景是class为background的背景</p>
                <p>通过相对定位和绝对定位,我把class为background的DIV移动到了我的位置。</p>
                <p>同时通过我的较大的z-index浮在了它的上面。 :)</p>
                <p style="text-align:right">——刘龙(liulo)</p>
            </div>
            <div class="background"></div>
        </div>
    </body>
    </html>

    效果:

    22222222222

    perfect!!完美兼容FF31、chrome35、以及IE7-11。

    总结

    经过 以上讨论,我们发现纯代码方面除了方法四,其他的都或多或少存在兼容性问题,当然你也可以通过判断浏览器使用javascript改变DOM,这样一来未免得不偿失。

    在需要兼容IE7、8的情况下,除了方法四,还可以用传统的方法——gif/png图片……

    ps:以上方法在IE6中均不可实现。

    建议阅读stackoverflow上的相关讨论:http://stackoverflow.com/questions/806000/transparent-background-but-not-the-content-text-images-inside-it-in-css-on#

  • 相关阅读:
    回溯法之图的着色问题
    回溯法基本思想
    L2-006 树的遍历
    P1540 机器翻译
    P1067 多项式输出
    C++STL之map映照容器
    C++STL之multiset多重集合容器
    C++STL之set集合容器
    C++之string基本字符系列容器
    C++STL之vector向量容器
  • 原文地址:https://www.cnblogs.com/liu-l/p/3890861.html
Copyright © 2020-2023  润新知