css Sub-Pixel Bug?!

时间:2021-05-08

jQuery之父John Resig写过一篇《Sub-Pixel Problems in CSS》,一个50px宽的div中有4个float的div,每个宽25%,然而各个浏览器对50*25%的理解有些纠结(demo):

随后Steven Wittens的《CSS Sub-pixel Background Misalignments》,测试了固定宽度的元素水平居中时父元素背景图片居中的差异,更让我们看到眼花(demo):

让人郁闷的是:不止IE,各浏览器的不同版本也有些许差异… 还好,现实工作中很少会碰到这种情形,遇到了也只是一个相对简单的情形,比较典型的应用场景是:某些QQ会员活动类的页面,背景一幅很宽大宏伟的1280px大图居中,中间区域980px居中,1024分辨率下980px外的部分能显示多少就显示多少,不出现横向滚动条,大于1024的分辨率则大图全部显示。 下面来看个简单的demo(为了方便发现及总结问题,外围大图宽400px(对应上面的1280px),中间200px掏空(对应上面的980px),中间图宽200px):

XML/HTML Code复制内容到剪贴板
  • <!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  • <htmlxmlns="http://www.w3.org/1999/xhtml">
  • <head>
  • <metacontent="text/html;charset=utf-8"http-equiv="Content-Type"/>
  • <title>Sub-Pixel</title>
  • <styletype="text/css">
  • body,div,p{margin:0;padding:0;}
  • body{text-align:center;}
  • button{margin:1em;padding:01em;}
  • #pg,body{background-position:center0;background-repeat:no-repeat;}
  • body{background-image:url('http://webteam.tencent.com/wp-content/uploads/2010/3/1749_003.jpg');}
  • #pg{margin:0auto;width:200px;height:200px;background-image:url('http://webteam.tencent.com/wp-content/uploads/2010/3/1749_004.jpg');}
  • </style>
  • </head>
  • <body>
  • <divid="pg"></div>
  • </body>
  • </html>

  • 拖动浏览器边缘改变浏览器窗口的宽度,可以看到在某些时候body和#pg在右侧的交界处会有1px的空隙,这个问题存在于IE6/Chrome3/Safari4中。 以搜集IE BUG闻名的PIE(Position Is Everything)也有一篇《IE Background Positioning Bug》,不过其中的外层元素是固定宽度,对我们用处也不大。同事77总结了两个方法:

  • 切图时body和#pg的图片不要分开,合在一张大图上,然后对body写背景图片居中,图片太大的话则切为多个相同宽度的小图,通过嵌套多个div来写,比如


  • 复制代码代码如下:
    <div class="bg1">
    <div class="bg2">
    <div class="bg3">
    <div id="pg"></div>
    </div>
    </div>
    </div>
  • body大图中间挖空区域多留几个像素,比如现在是200px,切图时为198px,两侧各多留1px
  • 方法1在多数情况下很完美,不过也有某些个案不能使用这种方法;方法2对于body和#pg交界处比较淡化的图片来说非常适合,比如ISD Webteam博客的关于页面,不过有些时候交界处这1px会衔接不自然得非常明显,是我们这些追求完美的页面重构工程师所不能容忍的。 下面我们改变点结构来具体分析一下(注:此例为临时用例,下文中提到的body/#pg与之无关):

    复制代码代码如下:
    <!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">
    <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Sub-Pixel</title>
    <style type="text/css">
    body, div, p{margin:0;padding:0;}
    body{text-align:center;}
    button{margin:1em;padding:0 1em;}
    #pg, #hd{background-position:center 0;background-repeat:no-repeat;}
    #pg{background-image:url('http://webteam.tencent.com/wp-content/uploads/2010/3/1749_003.jpg');}
    #hd{margin:0 auto;width:200px;height:200px;background-image:url('http://webteam.tencent.com/wp-content/uploads/2010/3/1749_004.jpg');}
    </style>
    </head>
    <body>
    <div id="pg">
    <div id="hd"></div>
    </div>
    <button id="sum">+1</button><button id="substruction">-1</button>
    <p>#pg宽度为<strong id="current"></strong>px</p>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script>
    $(document).ready(function(){
    var pg = $('#pg');
    var current = $('#current');
    function getWidth(){
    current.text(pg.width());
    }
    getWidth();
    $(window).resize(getWidth);
    $('#sum').click(function(){
    pg.width(pg.width() + 1);
    getWidth();
    });
    $('#substruction').click(function(){
    pg.width(pg.width() - 1);
    getWidth();
    });
    })
    </script>
    </body>
    </html>

    通过连续的点击+1/-1按钮可以看出,当#pg宽度>#pg背景图片宽度(400px)且为奇数时,右侧才会出现这1px的空隙

    当我们纠结于奇偶数的时候,神奇的
    body{margin-left:1px}

    出现了,详见《CSS IE one pixel image offset hack》。当设置了body的左外边距为1px时,不管奇偶数都不会出现这个1px的空隙了。不过,当body宽度小于背景大图宽度(这里是400px)且为偶数时,左侧交界处却出现了1px的空隙

    看来只有用JS解决了,是当body宽度≥背景大图宽度(这里是400px)时,令body margin-left:1px,<时则去除margin-left:1px 全部代码如下:


    复制代码代码如下:
    <!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">
    <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Sub-Pixel</title>
    <style type="text/css">
    body, div, p{margin:0;padding:0;}
    body{text-align:center;}
    button{margin:1em;padding:0 1em;}
    #pg, body{background-position:center 0;background-repeat:no-repeat;}
    body{background-image:url('http://webteam.tencent.com/wp-content/uploads/2010/3/1749_003.jpg');}
    #pg{margin:0 auto;width:200px;height:200px;background-image:url('http://webteam.tencent.com/wp-content/uploads/2010/3/1749_004.jpg');}
    .fix-bg{margin-left:1px;}
    </style>
    </head>
    <body>
    <div id="pg"></div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script>
    $(document).ready(function(){
    var body = $('body');
    function fixBg() {
    (body.width() >= 400) ? body.addClass('fix-bg') : body.removeClass('fix-bg');
    }
    fixBg();
    $(window).resize(fixBg);
    })
    </script>
    </body>
    </html>
    后记
    眼看就要圆满了,转念一想:“如果大图宽度是奇数,会出现这个问题吗?如果出现了,那怎么搞捏?” 额…介个,介个…

    声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

    相关文章