在 margin系列之佈局篇 一文結尾時,咱們談到了聖盃佈局,說這個佈局的實現自己存在了一些問題:「在IE6/7下報廢,不過不用慌,由於它可被修復」。css
下面節選一段來自網路上對聖盃的描述(略有調整):html
聖盃是宗教傳說中的聖物,耶穌曾經用這個杯子吩咐門徒喝下里面象徵他的血的紅葡萄酒,藉此創立了受難記念儀式。由於這個特殊的緣由,後來有些人認爲這個杯子具備某種神奇的能力。不少傳說相信,若是能找到這個聖盃而喝下其盛過的水就將返老還童、死而復生而且得到永生,這個傳說普遍延續到不少文學、影視、遊戲等做品中。瀏覽器
而所謂的聖盃佈局也並非一個具象的形容,更多的是指借但願於它可以實現某種特殊的佈局。ide
這種特殊佈局的需求是:側邊欄寬度固定,主內容欄寬度自適應,而且須要將主內容欄放在側邊欄前面,以便優先渲染(不管是兩欄或者三欄,需求都是同樣的)。佈局
在 margin系列之佈局篇 裏,咱們用聖盃佈局作了 圖0
的效果。測試
下面是咱們在上篇文章中寫的聖盃佈局核心代碼(固然,這個 #demo
容器你也能夠利用 body
來取代):code
1 2 3 4 5 6 7 8 |
<div id="demo"> <header id="hd">頭部</header> <div id="bd"> <div id="main">主內容欄自適應寬度</div> <aside id="aside">側邊欄固定寬度</aside> </div> <footer id="ft">底部</footer> </div> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#demo { width: 80%; } #bd { *zoom: 1; overflow: hidden; padding-left: 210px; } #main { float: left; width: 100%; } #aside { _display: inline; float: left; position: relative; left: -210px; width: 200px; margin-left: -100%; } |
你們可使用各類瀏覽器來測試一下這個示例 聖盃:左欄固定主內容自適應htm
通常狀況下,你會發現除了IE6
外,其它的瀏覽器看起來都算正常,然而問題的範圍可能並不只限於這些,大部分問題沒被看出只不過是由於沒到達邊界。blog
問題列表:
IE6
佈局錯亂,側邊欄位置不對;IE7
resize窗口時,側邊欄會跳動;IE7及其它瀏覽器
,當窗口縮小到主內容欄的寬度小於側邊欄的寬度時,佈局錯亂;上面這幾個問題,你們其實均可以本身去測測看,應該是當前的實現中都存在的。
對於第3點,咱們看看上述的代碼實現,仍是能很是輕鬆的理解的。由於側邊欄定義了 margin-left: -100%
,在這個場景中,100%
其實就等同於主內容欄的寬度。若是主內容欄的寬度小於側邊欄,那麼側邊欄偏移了一個比本身小的寬度,天然是放不下本身的。
對於第1點,這個就有點意思了,基本上這又算是IE6的一個Bug,描述一下這個Bug的現象:
在IE6中,假定是處於默認的書寫模式下,當一個浮動的元素定義了margin的值是一個百分比,那麼此時,浮動元素的margin百分比參照最近的清除了浮動的包含塊的父元素的寬度進行計算,或者參照body。(然而標準描述只是參考包含塊的寬度進行計算,詳情請參閱我以前的文章 margin系列之百分比)
我會用一段僞代碼來詳述這個事,代碼以下:
1 |
body > c > b > a |
假設上述代碼中的 a
就是咱們說的浮動元素,正常狀況下 a
設置了一個百分比的margin,百分比是要參考 b
的寬度進行計算的。
而後 IE6
並無實現這個規則,它的特徵是:
a
定義了百分比的margin,假設它的祖先元素 b
和 c
都沒有清除浮動,那麼就會參照 body
的寬度進行百分比換算;b
清除了浮動,那麼就會參照 c
的寬度進行百分比換算;對於這個Bug,我寫了一個示例,你們能夠對照着描述來看這個例子:浮動margin百分比在ie6上的Bug
好了,知道了在 IE6
中有這個Bug以後,關於問題列表中的第1點,咱們就也可以理解了,由於 position: relative; left: -210px;
這個定義對於 IE6
來說,實際上是多餘的。
對於第2點,應該是在resize過程當中,不斷的重繪形成的,它須要不斷的去計算這個百分比的使用值。
因此若是想使得聖盃佈局變得更靠譜一些,咱們要麼就是見招拆招,修復這個問題(好比說爲 IE6
重置掉 position: relative; left: -210px;
定義),要麼就避免趕上這些問題,我更喜歡第二種的方式。
咱們如何作才能避免趕上這些問題?
其實咱們能夠細看一下,問題列表中的幾點,其實都是因浮動元素的margin百分比引起的。既然浮動元素的margin百分比,在各瀏覽器下須要差別化處理,那麼幹脆棄用百分比,改用固定值(複雜度其實並無上升,由於用百分比的時候,還得給left
定義一個固定的偏移量)。
那麼,新的問題來了。若是改用margin固定值,咱們要如何知道這個固定值是多少?好比在這個佈局中咱們的容器寬度是視窗的 80%
,咱們沒法獲得側邊欄須要偏移的固定值是多少,除非咱們使用運算表達式 calc()
,可是它的兼容性並非咱們想要的。
這是由於主內容欄和側邊欄都是左浮動,而且側邊欄浮動在主內容欄後面,因此咱們須要讓側邊欄偏移 #main + #aside
的寬度,才能讓側邊欄出如今正確的位置。
因此,其實咱們能夠轉變一下思路,讓主內容欄和側邊欄朝不一樣的方向浮動,這樣的話,側邊欄只須要偏移自身的寬度就能出如今正確的位置上,不在須要使用margin百分比值。
咱們按照前面說的將代碼調整一下,HTML不變:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#demo { width: 80%; } #bd { *zoom: 1; overflow: hidden; padding-left: 210px; } #main { float: right; width: 100%; } #aside { _display: inline; float: left; width: 200px; margin: 0 10px 0 -210px; } |
咱們來看看這個 進化的聖盃:左欄固定主內容自適應 效果,你會欣喜的發現,問題列表中的3個問題都被咱們跳過了,這是一個更健康的實現。
固然,它也是能夠任意調整列呈現順序的,咱們只須要這樣就行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#demo { width: 80%; } #bd { *zoom: 1; overflow: hidden; padding-right: 210px; } #main { float: left; width: 100%; } #aside { _display: inline; float: right; width: 200px; margin: 0 -210px 0 10px; } |
因而咱們就獲得了一個 進化的聖盃:右欄固定主內容自適應 的佈局。
整體來說,聖盃佈局只是有能力達成咱們的需求,但就其自己來說並非太先進的佈局,靈活性相對侷限。
另外,你可能關注到了代碼中出現的 margin
定義,它並非一個單純的負值,而是多了一個 10px
,這實際上是爲了解決 IE6/7
右浮動子元素的向右負偏移量最大隻能是自身寬度的問題(感興趣的童鞋能夠看看這個測試:右浮動margin-right負值在ie67上的bug),因此額外處理的間隙,但這其實並不影響其餘瀏覽器。
本文,更多的在於補全以前的那篇文章,算個簡單的完結。本意其實並不在於說讓你們去折騰那些古老而無趣的瀏覽器,而是但願看到的是對待任何事情,咱們首先要以爲它能夠解決,而後再抽絲剝繭的去實現它。未知並不可怕,可怕是恐懼未知。