聖盃佈局和雙飛翼佈局的理解與思考

聖盃佈局和雙飛翼佈局是前端工程師須要平常掌握的重要佈局方式。二者的功能相同,都是爲了實現一個兩側寬度固定,中間寬度自適應的三欄佈局
javascript

 
聖盃佈局與雙飛翼佈局

 

聖盃佈局來源於文章In Search of the Holy Grail,而雙飛翼佈局來源於淘寶UED。雖然二者的實現方法略有差別,不過都遵循瞭如下要點:css

  • 兩側寬度固定,中間寬度自適應
  • 中間部分在DOM結構上優先,以便先行渲染
  • 容許三列中的任意一列成爲最高列
  • 只須要使用一個額外的<div>標籤

下面我將依次介紹聖盃佈局和雙飛翼佈局的實現方法,並在最後根據我的思考對原有方法作出一些修改,給出其它一些可行的方案。html

聖盃佈局

1. DOM結構

<div id="header"></div> <div id="container"> <div id="center" class="column"></div> <div id="left" class="column"></div> <div id="right" class="column"></div> </div> <div id="footer"></div> 

首先定義出整個佈局的DOM結構,主體部分是由container包裹的center,left,right三列,其中center定義在最前面。前端

2. CSS代碼

假設左側的固定寬度爲200px,右側的固定寬度爲150px,則首先在container上設置:java

#container { padding-left: 200px; padding-right: 150px; } 

爲左右兩列預留出相應的空間,獲得以下示意圖:git

 
建立佈局框架

隨後分別爲三列設置寬度與浮動,同時對footer設置清除浮動:github

#container .column { float: left; } #center { width: 100%; } #left { width: 200px; } #right { width: 150px; } #footer { clear: both; } 

獲得以下效果:前端工程師

 
設置寬度和清除浮動

根據浮動的特性,因爲center的寬度爲100%,即佔據了第一行的全部空間,因此leftright被「擠」到了第二行。框架

接下來的工做是將left放置到以前預留出的位置上,這裏使用負外邊距(nagetive margin)ide

#left { width: 200px; margin-left: -100%; } 

獲得:

 
將left移動到預留位置-1

隨後還須要使用定位(position)方法:

#left { width: 200px; margin-left: -100%; position: relative; right: 200px; } 

這裏使用position: relativeright: 200pxleft的位置在原有位置基礎上左移200px,以完成left的放置:

 
將left移動到預留位置-2

接下來放置right,只需添加一條聲明便可:

#right { width: 150px; margin-right: -150px; } 

獲得最終的效果圖:

 
將right移動到預留位置

至此,佈局效果完成。不過還須要考慮最後一步,那就是頁面的最小寬度:要想保證該佈局效果正常顯示,因爲兩側都具備固定的寬度,因此須要給定頁面一個最小的寬度,但這並不僅是簡單的200+150=350px。回想以前left使用了position: relative,因此就意味着在center開始的區域,還存在着一個left的寬度。因此頁面的最小寬度應該設置爲200+150+200=550px:

body { min-width: 550px; } 

綜上所述,聖盃佈局的CSS代碼爲:

body { min-width: 550px; } #container { padding-left: 200px; padding-right: 150px; } #container .column { float: left; } #center { width: 100%; } #left { width: 200px; margin-left: -100%; position: relative; right: 200px; } #right { width: 150px; margin-right: -150px; } #footer { clear: both; } 

關於聖盃佈局的示例,可參考:聖盃佈局

最後提醒一下不少朋友可能會忽略的小細節:在#center中,包含了一條聲明width: 100%,這是中間欄可以作到自適應的關鍵。可能會有朋友認爲不須要設置這條聲明,由於以爲center在不設置寬度的狀況下會默認將寬度設置爲父元素(container)的100%寬度。但須要注意到,center是浮動元素,因爲浮動具備包裹性,在不顯式設置寬度的狀況下會自動「收縮」到內容的尺寸大小。若是去掉width: 100%,則當中間欄不包含或者包含較少內容時,整個佈局會「崩掉」,而達不到這樣的效果:

 
中間欄僅包含較少內容

 

雙飛翼佈局

1. DOM結構

<body> <div id="header"></div> <div id="container" class="column"> <div id="center"></div> </div> <div id="left" class="column"></div> <div id="right" class="column"></div> <div id="footer"></div> <body> 

雙飛翼佈局的DOM結構與聖盃佈局的區別是用container僅包裹住center,另外將.column類從center移至container上。

2. CSS代碼

按照與聖盃佈局相同的思路,首先設置各列的寬度與浮動,而且爲左右兩列預留出空間,以及爲footer設置浮動清除:

#container { width: 100%; } .column { float: left; } #center { margin-left: 200px; margin-right: 150px; } #left { width: 200px; } #right { width: 150px; } #footer { clear: both; } 

獲得以下效果示意圖:

 
雙飛翼佈局初始設置

以上代碼將container,left,right設置爲float: left,而在container內部,center因爲沒有設置浮動,因此其寬度默認爲container的100%寬度,經過對其設置margin-leftmargin-right爲左右兩列預留出了空間。

left放置到預留位置:

#left { width: 200px; margin-left: -100%; } 

獲得:

 
放置left到預留位置

right放置到預留位置:

#right { width: 150px; margin-left: -150px; } 

獲得最終效果:

 
雙飛翼佈局最終效果

最後計算最小頁面寬度:因爲雙飛翼佈局沒有用到position:relative進行定位,因此最小頁面寬度應該爲200+150=350px。可是當頁面寬度縮小到350px附近時,會擠佔中間欄的寬度,使得其內容被右側欄覆蓋,以下所示:

 
中間欄內容被覆蓋

 

所以在設置最小頁面寬度時,應該適當增長一些寬度以供中間欄使用(假設爲150px),則有:

body { min-width: 500px; } 

至此雙飛翼佈局大功告成!其佈局總體代碼爲:

body { min-width: 500px; } #container { width: 100%; } .column { float: left; } #center { margin-left: 200px; margin-right: 150px; } #left { width: 200px; margin-left: -100%; } #right { width: 150px; margin-left: -150px; } #footer { clear: both; } 

關於雙飛翼佈局的示例,可參考:雙飛翼佈局

總結與思考

經過對聖盃佈局和雙飛翼佈局的介紹能夠看出,聖盃佈局在DOM結構上顯得更加直觀和天然,且在平常開發過程當中,更容易造成這樣的DOM結構(一般<aside><article>/<section>一塊兒被嵌套在<main>中);而雙飛翼佈局在實現上因爲不須要使用定位,因此更加簡潔,且容許的頁面最小寬度一般比聖盃佈局更小。

其實經過思考不難發現,二者在代碼實現上都額外引入了一個<div>標籤,其目的都是爲了既能保證中間欄產生浮動(浮動後還必須顯式設置寬度),又能限制自身寬度爲兩側欄留出空間。

從這個角度出發,若是去掉額外添加的<div>標籤,可否完成相同的佈局呢?答案是確定的,不過這須要在兼容性上作出犧牲

DOM結構

<div id="header"></div> <div id="center" class="column"></div> <div id="left" class="column"></div> <div id="right" class="column"></div> <div id="footer"></div> 

去掉額外的<div>標籤後,獲得的DOM結構如上所示,基於雙飛翼佈局的實現思路,只須要在center上作出修改:

1. 使用calc()

.column { float: left; } #center { margin-left: 200px; margin-right: 150px; width: calc(100% - 350px); } 

經過calc()能夠十分方便地計算出center應該佔據的自適應寬度,目前calc()支持到IE9

2. 使用border-box

.column { float: left; } #center { padding-left: 200px; padding-right: 150px; box-sizing: border-box; width: 100%; } 

使用border-box能夠將center的整個盒模型寬度設置爲父元素的100%寬度,此時再利用padding-leftpadding-right能夠自動獲得中間欄的自適應寬度。不過須要注意的是,因爲padding是盒子的一部分,因此padding部分會具備中間欄的背景色,當中間欄高於側欄時,會出現這樣的狀況:

 
padding背景色影響左側空間

目前box-sizing支持到IE8

3. 使用flex

這裏使用flex仍是須要與聖盃佈局相同的DOM結構,不過在實現上將更加簡單:

<!-- DOM結構 --> <div id="container"> <div id="center"></div> <div id="left"></div> <div id="right"></div> </div> 

CSS代碼以下:

#container { display: flex; } #center { flex: 1; } #left { flex: 0 0 200px; order: -1; } #right { flex: 0 0 150px; } 

結語

以上就是本人在學習聖盃佈局和雙飛翼佈局過程當中的一些總結和認識,文章若有錯誤,歡迎你們多多指教~

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息