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」。由於每一種盒模型的解析方式都存在着利與弊,因此可使用這項技術是有好處的。但說回來,對於這種屬性的任何具體的落實,都會面臨一些瀏覽器尚不支持的尷尬狀況。

相關文章
相關標籤/搜索