寫在前面
最近看到《圖解CSS3》的佈局部分,結合本身之前閱讀過的一些佈局方面的知識,這裏進行一次基於CSS二、3的各類佈局的方法總結。css
在拿到設計稿時,做爲一個前端人員,咱們首先會作的應該是爲設計圖大體地劃分區域,而後選擇一種最合理的,結構清晰的佈局。下面我先根據一些典型的網站案例列舉一下幾種常見的頁面佈局。html
這個是咱們比較常見的佈局,其頁面的頂部通常放置橫網站的標誌或Banner廣告,下方左側是導航欄菜單,下方右側則用於放置網頁正文等主要內容。
Segmentfault的主頁就是T型佈局的。因爲網頁太長了。。沒有截取底部。前端
國字型佈局下最上面是網站的標題以及橫幅廣告條,接下來是網站的主要內寄,左右分列一些小條內容,中問是主要部分,與左右一塊兒羅列到底,最下方是網站的一些基本信息、聯繫方式、版權聲明等。
案例圖片來自騰訊11年的一道前段筆試題,有興趣的同窗能夠去看一下。2011騰訊前端面試稿css3
POP佈局指頁面佈局像一張宣傳海報,以一張精美圖片做爲頁面的設計中心。經常使用於時尚類站點。優勢顯而易見:漂亮吸引人。缺點就是速度慢。
人大的主頁就相似這種佈局。面試
顧名思義,就是網頁主體分爲左右兩大塊,多見爲後臺管理系統頁面。通常左右佈局型的頁面須要作到兩列等高。shell
如:ide
參見蘋果的官網,相似於整屏顯示的網頁都爲上下佈局。佈局
關於佈局的類型就先說這麼多,下面來總結一下上述的佈局怎麼來實現。下面提一下你們應該都很熟悉的兩大布局方法。聖盃佈局和雙飛燕佈局。其實這兩種方法通常多用國字型佈局上。就是針對三行三列佈局的。進行相應的改造也能夠用在T字型佈局上。用這兩種方法能夠很好地解決主體部分優先加載的問題。測試
基礎佈局:flex
<div id="header"></div> <div id="main"></div> <div id="footer"></div>
重點來看main部分的代碼
<style type="text/css"> #main { overflow: hidden; /*修整由子元素浮動引發的高度塌陷問題*/ zoom: 1;/*低版本ie下:觸發haslayout屬性,修整由子元素浮動引發的高度塌陷問題*/ /*將主體部分左右側預留出左右邊欄大小的空白位置*/ padding: 0 300px 0 220px; } .m_content, .m_leftside, .m_rightside { float: left; /*目的是將左右側邊欄拉回*/ position: relative; } .m_content { width: 100%; } .m_leftside { width: 220px; /*因爲m_content佔據了100%空間,因此須要用負的margin值將左邊欄拉回*/ margin-left: -100%; /*將主體部分預留的左側補白區域填充滿*/ left: -220px; } .m_rightside { width: 300px; /*用負的margin值將右邊欄拉回自身大小個像素單位*/ margin-left: -300px; /*將主體部分預留的右側補白區域填充滿*/ left: 300px; } </style> <div id="main"> <div class="m_content">這裏是主體</div> <div class="m_leftside">這是左側邊欄</div> <div class="m_rightside">這是右側邊欄</div> </div>
以上就是聖盃佈局方法,基本思路是運用浮動加定位的方法,缺點是代碼較複雜,不能模擬三欄等高效果。
佈局的效果跟聖盃的同樣,代碼有所不一樣。雙飛燕佈局的代碼更加簡單,只是多加了一個div用來佈局。
基礎佈局部分代碼同樣。
main部分:
<style> #main {overflow: hidden;zoom: 1;}/*這裏不須要加padding了*/ .m_content, .m_leftside, .m_rightside {float: left;} .m_content {width: 100%;} /*用左右邊距將左右邊欄的位置預留出來*/ .m_c_wrap {margin-left: 220px;margin-right:300px;} .m_leftside {width: 220px;margin-left: -100%;} .m_rightside {width: 300px;margin-left: -300px;} </style> <div id="main"> <div class="m_content"> <!--正真的主體開始--> <div class="m_c_wrap">這裏是主體</div> </div> <div class="m_leftside">這是左側邊欄</div> <div class="m_rightside">這是右側邊欄</div> </div>
瞭解了以上兩種佈局的方法後,不少佈局都能寫得駕輕就熟了。可是應對多欄等高佈局還有點欠缺。那麼如今來談談多欄等高佈局的方法。
這裏詳細總結了等高佈局的八大方法 Click,我再談談實際項目中比較經常使用的,或者說比較簡單的三種方法。
好比咱們須要作一個上圖的佈局,那麼須要截取這樣一個側邊的小圖片對側邊和內容部分包裹的元素進行背景平鋪,用來模擬出側邊欄的高度跟內容高度一致的視覺效果。
只須要將須要等高的若干欄設置display
屬性爲table-cell
;若其中一列但願是自適應寬度,還需將父元素的display
設置成table
,width
爲100%
。
代碼以下:
<style> #main {display: table;width: 100%} .m_content {display: table-cell;width: auto;} .m_rightside {display: table-cell;width: 200px;} </style> <div id="main"> <div class="m_content"></div> <div class="m_rightside"></div> </div>
這是前不久在網上看到的一種辦法,實質就是爲欄目添加一個足夠大的padding-bottom
值,將欄目撐開,而後再添加相同大小的負的margin-bottom
值將內容移動回來。注意要在負盒子上加上overflow: hidden
的屬性。
代碼以下:
<style> #main {width: 100%;overflow: hidden;} .m_content {width: auto;float:left;} .m_rightside {width: 200px;padding-bottom: 10000px;margin-bottom: 10000px;float:left;} </style> <div id="main"> <div class="m_content"></div> <div class="m_rightside"></div> </div>
CSS2的佈局方法總結獲得這裏就告一段落了。如今來看看CSS3新增的佈局方法。
由於書面上的解釋比較抽象,我這裏就儘可能說得簡單通俗一點。
要進行flex佈局,須要定義一個flex容器,而後再處理其子項目。只要一個容器被定義爲flex容器,那麼其子元素都稱做它的子項目。
flex佈局的基本思想是經過flex容器來伸縮控制子項目的寬度和高度,以此來徹底填充flex容器的可用空間。子項目的寬高、排列方式等都是經過設置相關屬性改變的。那麼以這種方式佈局上述幾種佈局就簡單多了。子項目默認的排列方式與浮動佈局略爲類似。
flex容器的定義方式:
div{display:flex}
flex容器分爲主軸和側軸。主軸決定容器子項的排列方向。側軸與主軸相互垂直。主軸可有垂直和水平兩個方向。
flex容器可對子項進行的操控有:(即設置在容器的屬性。這個很重要!)
子項目的排列方向(也就是剛剛說的定義主軸)—— flex-direction
子項目的換行方式(就是超出flex容器跨度時換不換行=。=怎麼換) —— flex-wrap
同時進行子項目排列方向和換行方式的設定 —— flex-flow
子項目在主軸的對齊方式(想象成文字的對齊方式就容易理解了) —— justify-content
子項目在側軸的對齊方式 —— align-items
同時進行子項目主軸和側軸對齊方式的設定 —— align-content
下面來看看每個屬性的取值和實現效果
flex-direction:
div{ flex-direction: row /*水平排列,默認*/ <row-reverse> /*水平排列,但子項目從右側開始排列*/ <column> /*垂直排列*/ <column-reverse>; /*垂直排列,但子項目從下側開始排列*/ }
測試中我令flex容器的寬度爲100px,高爲200px,定義了5個未定義寬高的子項目,演示了上述的四種排列狀況。效果:
這裏須要說明的是:在未定義子項目的伸縮方式時,默認是按子項目自己大小渲染的。
flex-wrap
div{ flex-direction: nowrap /*當子項目在主軸上的總跨度大於主軸長度時,不進行換行,而是縮小每一個子項目的跨度。默認*/ <wrap> /*---同上---進行換行顯示*/ <wrap-reverse> /*從側軸的末端進行換行(在主軸的排列方向不變)。實際不經常使用*/ }
測試中我定義了每一個子項目的寬度爲30px,flex容器仍是原來的100px寬。效果:
因爲這裏設定的是子項目寬度,因此對於主軸爲垂直方向的容器子項沒什麼影響。
flex-flow
div{ flex-flow: <flex-direction> || <flex-wrap>; /*就是上述兩個屬性的結合簡寫 默認:flex-flow:row nowrap*/ }
justify-content
div{ justify-content: flex-start /*以項目開始進行排列的那端進行對齊,默認左對齊*/ <flex-end> /*以項目結束排列的那端進行對齊,默認右對齊*/ <center> /*居中對齊,默認水平居中*/ /*兩端對齊且項目之間的間隔都相等(貼邊顯示)*/ <space-between> /*第一個元素前的空間以及最後一個元素後的空間爲其餘空白空間的一半下平均分佈*/ <space-around> }
測試時我設定了flex容器寬高都爲200px,子項沒有設定寬高。 效果:
主軸爲水平方向時:
主軸爲水平垂直時:
align-items
div{ align-items: flex-start /*側軸起始點對齊*/ <flex-end> /*側軸終止點對齊*/ <center> /*側軸中點點對齊*/ /*項目的第一行文字的基線對齊*/ <baseline> /*默認值,若是項目未設定寬(高度),則佔滿整個容器側軸跨度*/ <stretch> }
最後的baseline看起來跟flex-start沒啥區別,由於我給每一個子項設置高度。設置高度後:
align-content
div{ align-content: flex-start /*與側軸起始點對齊*/ <flex-end> /*與側軸終止點對齊*/ <center> /*與側軸中點點對齊*/ /*與側軸兩端對齊,各子項在各軸上的間距相等*/ <space-between> /*各子項在各軸上的間距相等,項目間距比邊距間距大一倍*/ <space-around> /*項目佔滿整個側軸*/ <stretch> }
上面已提到過,對於單軸線的子項來講,本屬性不起做用。可是默認狀況下是隻有子項目是一根軸線的(flex-wrap
默認是nowrap
),因此要使這個屬性看到效果,必須設置flex-wrap
。
已下是flex-wrap
爲wrap
的幾種狀況。
如下這些屬性設置在子項上。
子項自身的操控有
子項目的排列順序 —— order
子項目的放大比例 —— flex-grow
默認爲0,即若是主軸上有剩餘空間,也不放大子項。
子項目的縮小比例 —— flex-shrink
默認爲1,即若是主軸空間不足,即縮小子項。
同時設定前三者 —— flex
設定單個項目其自身在側軸的對齊方式 —— align-self
那麼分別來看看每一個屬性的取值和實現效果()
order
利用這個屬性能夠解決某個區塊優先加載可是在頁面上的顯示較靠後的問題。
div .item {order:<integer>} /*數值越大,排列越靠後。默認爲0*/
這裏我設置了第一個子項的order爲1。
flex-grow
若是全部項目的flex-grow屬性都爲1,則它們將等分剩餘空間(若是有的話)。若是一個項目的flex-grow屬性爲2,其餘項目都爲1,則前者佔據的空間將比其餘項多一倍。
div .item {flex-grow:<number>}
設置flex-grow前:
設置後:
第二個項目的flex-grow爲2,其餘爲0:
<注意這個時候就不須要給子項設置寬度了>
flex-shrink
若是全部項目的flex-shrink屬性都爲1,當空間不足時,都將等比例縮小。若是一個項目的flex-shrink屬性爲0,其餘項目都爲1,則空間不足時,前者不縮小。
div .item {flex-shrink:<number>}
我給每一個子項設定了200px的寬度,而flex容器寬度爲500px,這時候若不設置flex-shrink,則每一個項目都會以相同比例縮小自身大小來適應容器。
此時我給第二個項目設置了flex-shrink: 0;
該項目大小不變。
flex-basis
這個屬性設置子項在主軸上的跨度,簡單地說就是設置寬高。
div .item {flex-basis:<length> | auto/*auto是默認值,就是項目自己大小*/}
flex
這個就是把flex-grow、flew-shrink、flex-basis結合一塊兒的寫法啦=。=
div .item {flex:none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]}
flex-grow必須。默認爲0 1 auto。
align-self
這個屬性用來單獨設定某個子項目在側軸的對齊方式。
div .item {align-self:flex-start|flex-end|center|baseline|stretch}
有關flex佈局的方法就總結和介紹到這裏了。有興趣看能夠看一下下面大大們寫的相關方面的文章。
Flex佈局教程——阮一峯 傳送門
A Complete Guide to Flexbox 傳送門2
一個完整的Flexbox指南 傳送門3
下邊把利用flex佈局實現上述幾種佈局的代碼貼出來(可有多種實現方法)。
T佈局
<!--css--> <style type="text/css"> *{margin: 0;padding: 0;} header, footer {background: sandybrown;height: 50px;} section {display: flex;align-items: flex-start;height: 500px;} article {order: 1;flex: 3;align-self: stretch;background: wheat;} aside {flex: 1;background: seashell;height: 100px;} </style> <!--html--> <header></header> <section> <article></article> <aside></aside> </section> <footer></footer>
國字型佈局
<!--css--> <style type="text/css"> *{margin: 0;padding: 0;} header, footer {background: sandybrown;height: 50px;} section {display: flex;align-items: flex-start;height: 500px;} article {order: 1;flex: 3;align-self: stretch;background: wheat;} aside {flex: 1;background: seashell;height: 100px;} section.sidebar {order: 2;flex: 1;height: 100px;background: seashell;} </style> <!--html--> <header></header> <section> <article></article> <aside></aside> <section class="sidebar"></section> </section> <footer></footer>
等高佈局
真心簡單。
<!--css--> <style type="text/css"> *{margin: 0;padding: 0;} html,body {height: 100%;} section {display: flex;height: 100%;} article {order: 1;flex: 3;background: wheat;} aside {flex: 1;background: seashell;} </style> <!--html--> <header></header> <section> <article></article> <aside></aside> <section class="sidebar"></section> </section> <footer></footer>
拖了半個多月的博文。。也算是寫完了,感謝你們閱讀。