IE浏览器和CSS盒模型

IE浏览器和更符合WEB标准的现代浏览器之间的差异在CSS盒模型这个问题上为不少前端初学者制造了很多的麻烦。由于盒模型是浏览器用来计算元素总宽度和高度的保证,因此就不难理解为何当浏览器计算出不一样结果时人们会如此的迷惑和丧气。css

尽管CSS盒模型是如何工做的已经在其余很是多的场合上被一次次的解释和说明,我却依然会常常在讨论会和邮件交流列表上看到关于这个问题的提问,也会不期的偶遇到一些在不复合标准的浏览器(IE)环境中开发出来的站点。这也就是为何我会写这篇文章的缘由,同时很大程度上这篇文章也算作是较早的时候给瑞典杂志《CAP&Design》写的另外一篇文章的翻译。html

若是你已经了解了CSS盒模型在兼容性上的差别以及如何处理IE浏览器的问题,那就请飘过——这里要谈的没任何新的东西。若是你对为何IE和其余浏览器会显示出不一样大小的盒子一无所知,那就继续阅读吧。前端

CSS盒模型图解

下面是一幅关于应用了CSS的元素是如何显示它的尺寸的图示。css3

box-model.gif

在本篇文章中,全部的浏览器在计算盒模型总宽度时处理margin属性的方式都是一致的,因此咱们将更多的精力放在padding和border属性上。web

W3C盒模型

首先看一下《 the W3C box model》,这里所写出的标准,若是没问题的话,是应该被全部标准的现代浏览器及IE6和它的后续版本所遵循的。在W3C盒模型中,一个块级元素的总宽度按照以下的方程式计算:浏览器

总宽度 = margin-left + border-left + padding-left + width + padding-right + border-right + margin-right安全

对于高度也使用一样的计算方法,可是为了简便起见从如今开始我只说width。ide

IE盒模型

IE盒模型的计算方式和W3C的很类似,但有一点是很是不一样的,这就是:填充和边框并不被包含在计算的范围内。post

总宽度 = margin-left + width + margin-rightui

这就意味着一旦元素拥有横向的填充和/或边框,实际的内容区域(content area )就要扩大来创造出他们占据的空间。

关于IE的版本

IE5.5及更早的版本使用的是IE盒模型。不少人彷佛没注意到IE6及更新的版本在标准兼容模式(standards compliant mode)下使用的是W3C的盒模型标准。咱们说这是一个好消息由于这意味着此盒模型问题只会出如今IE5.5及其更早的版本中。只要为文档设置一个DOCTYPE,就会使得IE遵循标准兼容模式的方式工做。

解决问题

如今肯定了IE6及后续版本都会遵循标准兼容模式,那如今惟一要关注的事情就是如何令IE5.5及更早版本中的网页和其在更现代的浏览器中呈现出的是一致的。若是你目前就遇到了这个问题,那么下面的几个方法会帮助到你,我以个人喜爱为它们列出了优先顺序。

  1. 避免致使这个问题的情景
  2. 插入额外的标记
  3. 使用条件注释判断语句
  4. 使用CSS hacks

由于这个由盒模型解析方式不一样致使的问题每每只是针对表象上的显示,因此我我的偏好的方法就是尽可能避免不去触发IE5.*/Win的这个BUG,而有些时候会不可避免的遇到,那我就会使用下面介绍的方法中的一个。

1.避免致使这个问题的情景

这是个人首选,很简单,就是避免为一个元素同时设置width和padding值或者width和border值,再或者width同时和它们两个值。这确保了全部的浏览器都会同样的去计算元素的总宽度,而不用考虑它们使用哪一种盒模型方式。

我这里拿一个例子说明,下面的HTML用来定义一个新闻列表:

<div id="news">
  <h2>News</h2>
  <ul>
    <li>
      <h3>News article 1</h3>
      <p>Lorem ipsum dolor sit amet</p>
    </li>
    <li>
      <h3>News article 2</h3>
      <p>Lorem ipsum dolor sit amet</p>
    </li>
  </ul>
</div>

为了获得一个250像素宽的列表,且应用1像素的边框和10像素的填充,会用到这样的CSS:

#news {
  padding:10px;
  border:1px solid;
  width:228px;
}

在符合标准的浏览器中,总宽度是250像素(1px left border + 10px left padding + width + 10px right padding + 1px right border)。但在IE5.5及更早的版本中,总宽度只是228像素,由于它并未计算边框和填充的值。

那么该如何避免这个问题呢?让咱们假设新闻列表在另外一个容器里,好比它在侧边栏(sidebar)里:

<div id="sidebar">
  <div id="news">
    ...
  </div>
</div>

若是是这样,你能够为父容器(sidebar)设置宽度来达到效果:

#sidebar {width:250px}
#news {
  padding:10px;
  border:1px solid;
}

2.插入额外的标记

若是状况不允许你使用第一种方法,那可使用插入额外的标记这个方法。仍是使用前面那个例子,此次咱们在#news里面插入一个标记:

<div id="news">
  <div>
  <h2>News</h2>
    <ul>
      ...
    </ul>
  </div>
</div>

使用以下的CSS:

#news {width:250px}
#news div {
  padding:10px;
  border:1px solid;
}

外层的元素提供宽度,包含在里面的元素提供边框和填充。

是否使用一个额外标记这种妥协式的方式的决定权在于开发者自己。避免使用这种方式的好处是显而易见的,可是一个额外的div标签除了会增长文件的体积和下降代码的可维护性以外,不会产生其余的不良影响。它不会影响到页面的无障碍性以及当CSS文档不存在的时候文档的可阅读性。此外,增长一个额外的标记还会为某些设计上的实现提供便利条件。

3.使用条件注释判断语句

若是没有合适的父容器来控制宽度也不能经过添加额外的标记解决问题,那针对IE 5.*/Win咱们就须要设置一个不一样的width值了。

个人建议,这么作最安全的方式就是使用条件注释判断语句(conditional comments,)这些内容只能在IE/Win中被解析,下面的代码只有在IE6如下的版本中被执行:

<!--[if lt IE 6]>
<style type="text/css">
  #news {width:250px}
</style>
<![endif]-->

若是你打算使用这个方法,我建议将所有的针对IE 5.*/Win的代码都转移到一个单独的CSS文件中来加载它:

<!--[if lt IE 6]>
<link rel="stylesheet" type="text/css" href="/css/ie5.css">
<![endif]-->

4.使用CSS hacks

最后你还能够经过使用一个CSS hack(CSS hack)来为IE 5.*/Win提供修改过的属性值。个人建议是尽可能不使用CSS hacks。顾名思义,它们是hacks,hacks是基于不一样浏览器对CSS解析不一样致使的无证错误之上的。由于如今依然有不少人在使用hacks,因此我在这里提一下也无妨。除非你明确的知道在作些什么,不然我仍是要建议你尽量的使用其余方法。

针对盒模型问题最简单的CSS hack是SBMH(The simplified box model hack),案例的HTML代码和上面第一个是同样的,CSS是:

#news {
  padding:10px;
  border:1px solid;
  width:250px;
  width:228px;
}

全部的浏览器都会看到并理解“width:250px”,但IE 5.*/Win不会读取下面的一行,width:228px,但这行会被其他的浏览器解析。因此最后,IE 5.*/Win获得的width值是250px,其余浏览器获得的是228px。这样,在所有的浏览器中咱们的新闻列表的总宽度就一致了。

总结:

我在本文中展现了如何避免或解决因CSS盒模型计算不一样而致使的问题的办法,你能够根据实际状况来选择使用哪种方法。

须要提到的是,可能在将来的某个时间,CSS3的“box-sizing”属性会给开发者选择盒模型解析方式的权利(在新发布的CSS草案中,允许开发者使用content-boxborder-box属性来选择盒模型解析的类型)。W3C的盒模型方式被称为“content-box”,IE的被称为“border-box”。由于每一种盒模型的解析方式都存在着利与弊,因此可使用这项技术是有好处的。但说回来,对于这种属性的任何具体的落实,都会面临一些浏览器尚不支持的尴尬状况。

相关文章
相关标签/搜索