2009年7月28日星期二

标准模式中的 IE 6&7 width 100% bug

在 web app 项目中经常遇到这个 bug,国外称之为 100% ≠ 100% bug,又分为两种:

  1. div 的宽度 100% ≠ 100% (IE 6&7)

    需求:

    1. 标准模式
    2. #container 局部滚动
    3. #asie 固定宽度
    4. #content 自适应宽度

    再复杂一点还会要求两列等高,可参考 http://www.99css.com/2009/07/equal-height-columns-with-cross-browser.html

    HTML

    <div id="container">
        <div id="wrapper">
            <div id="content">
                <h2>Content</h2>
            </div>
        </div>
        <div id="aside">
            <h2>Aside</h2>
        </div>
    </div>

    当然,别忘了 DTD 声明,因为这个只存在于标准模式

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    用之前介绍的 HTML5 写法亦可:

    <!DOCTYPE html>

    CSS

    /*简单重置*/
    body, div, h2{margin:0;padding:0;}
    /*设置颜色,方便区分*/
    #container{background:yellow;}
    #content{background:#FF8539;}
    #aside{background:#B9CAFF;}
    /*去除html默认滚动条*/
    html{overflow-y:hidden;}
    /*关键布局代码*/
    #container{height:300px;overflow:auto;}
    #wrapper{float:left;width:100%;margin-left:-200px;}
    #content{margin-left:200px;}
    #aside{float:right;width:200px;}

    #content, #aside{height:200px;}时,即高度未超出#container时一切正常

    #content, #aside{height:400px;}时,出现纵向滚动条

    正常显示效果如下:

    IE 6&7 中 bug 出现:

    原因:IE 6&7 滚动条的宽度未算在 100% 中,理想的状况是:#container 的宽度(100%) + #container 滚动条的宽度 = body 的 100%,W3C 对此的定义:

    In the case of a scrollbar being placed on an edge of the element's box, it should be inserted between the inner border edge and the outer padding edge. Any space taken up by the scrollbars should be taken out of (subtracted from the dimensions of) the containing block formed by the element with the scrollbars.

    Internet Explorer 100% Width Bug》中给出了思路:

    element_selector {
    width: expression(this.parentNode.offsetHeight >
    this.parentNode.scrollHeight ? '100%' :
    parseInt(this.parentNode.offsetWidth - XX) + 'px');
    }

    其中 XX 是滚动条的宽度,在 Windows XP 主题下是 17px,Windows 经典主题下稍微小一点,在其他第三方系统主题下有可能是不确定宽度。

    根据下图,简单改进一下即可

    解决方法

    #wrapper{#width:expression(this.parentNode.offsetHeight > this.parentNode.scrollHeight ? '100%' : parseInt(this.parentNode.clientWidth) + 'px');}

    当然,写在 js 中亦可,不过要注意不要漏掉 window 的 riseze 事件,另外,window 的 resize 事件在 IE 中有执行多次的 bug

  2. body 的宽度 100% ≠ 100% (仅 IE6)

    通常表现为 iframe 出现纵向滚动条时同时出现横向滚动条,简单粗暴的使用body{overflow-x:hidden;}是不负责任的,有时会截断要显示的内容

    第一个页面(父页面)

    <iframe frameborder="0" height="300" scrolling="auto" src="iframe.html" width="500">

    第二个页面(iframe)

    HTML

    <div></div>

    CSS

    body, div{margin:0;padding:0;}
    div{background-color:yellow;height:500px;}

    正常效果

    IE6

    解决方法(原理同上)

    body{_width:expression(this.parentNode.offsetHeight > this.parentNode.scrollHeight ? '100%' : parseInt(this.parentNode.clientWidth) + 'px');}

折腾了这么久,哥累了,哥真的希望 IE 只是个传说

2 条评论:

iVane Show 说...

图片看不到,图床坏了吧~

ytzong 说...

图片在 Picasa 上,被河蟹鸟,翻墙看吧