常規流
我們通(tōng)常講的(de)塊級元素與行内元素的(de)默認表現,就是它們在常規流中的(de)表現。有一個(gè)名爲display的(de) CSS 屬性可(kě)以修改它們的(de)表現形式。在默認情況下(xià),塊級元素的(de)display屬性值爲block,行内元素的(de)屬性值爲inline,如果你把某個(gè)a元素的(de)display屬性值改成block,那麽這(zhè)個(gè)a元素就會像一個(gè)塊級元素一樣表現自己了(le)。另外還(hái)有一個(gè)比較特殊的(de)屬性值爲inline-block,顧名思義是像行内元素那樣排列的(de)塊級元素,一般情況下(xià),在想要并列排列某些塊級元素的(de)時(shí)候,就可(kě)以把它們的(de)display屬性值改成inline-block(無獎問答(dá):爲什(shén)麽不直接改成inline呢(ne)?)
相對(duì)定位
一般的(de)教程會把相對(duì)定位和(hé)絕對(duì)定位一起放在浮動的(de)前面或者後面,而我選擇這(zhè)麽安排内容的(de)原因之一是我想要強調相對(duì)定位的(de)元素仍然在常規流中(事實上W3C标準 http://www.w3.org 也(yě)是如此安排目錄的(de))。
position:relative的(de)元素就擁有了(le)相對(duì)定位的(de)能力,而用(yòng)戶可(kě)以通(tōng)過上下(xià)左右(top、bottom、left、right)四個(gè)屬性值(但是通(tōng)常隻使用(yòng)top和(hé)left,因爲這(zhè)裏允許使用(yòng)負數,right = -left)來(lái)在視覺上“推走”這(zhè)個(gè)元素。相對(duì)定位最大(dà)的(de)特點就是,元素的(de)本體還(hái)在那裏,而用(yòng)戶看到的(de)則未必(上下(xià)左右都不設置或者爲0的(de)時(shí)候,元素仍舊(jiù)在那裏),定位方式是“相對(duì)于原位置定位”,因此被稱爲相對(duì)定位。而其真正在定位上的(de)應用(yòng),通(tōng)常不是在大(dà)框架的(de)布局,而是一些小地方、小細節的(de)微調,而其更常見的(de)用(yòng)法,會在下(xià)面再次提到。
當然一個(gè)超級普通(tōng)毫無特色常規流塊級元素根本無法滿足我們對(duì)豐富布局的(de)需求,所以出現了(le)人(rén)間大(dà)殺器——float。
浮動
當我們将某個(gè)元素的(de)float屬性改爲left或者right的(de)時(shí)候,這(zhè)個(gè)元素就成爲了(le)一個(gè)浮動的(de)塊級元素。
首先它仍然是一個(gè)塊級元素(如果它原本是一個(gè)内聯元素,那麽此時(shí)它也(yě)變成了(le)塊級元素)——擁有padding、border、margin,可(kě)以設置寬高(gāo)。其次它浮起來(lái)了(le):
它脫離了(le)常規流
它的(de)寬度變成了(le)它内容的(de)寬度
它向著(zhe)你規定的(de)方向擠成一堆
這(zhè)些事意味著(zhe)什(shén)麽呢(ne):
浮動元素的(de)寬度變成了(le)其内容所需的(de)最小寬度。如果這(zhè)個(gè)元素裏面還(hái)有一個(gè)常規塊級元素呢(ne)?那就要看這(zhè)個(gè)常規塊級元素多(duō)寬咯(它沒定義寬度,那還(hái)是100%)。
浮動元素後面的(de)常規元素看不見他(tā)(因爲他(tā)們不在同一個(gè)“流”裏了(le)),浮動元素的(de)父元素也(yě)看不見他(tā)(視而不見),隻有行框看得(de)見——文字會繞著(zhe)它們排列。
浮動元素會按著(zhe)所規定的(de)方向一個(gè)接一個(gè)水(shuǐ)平排列,如果水(shuǐ)平位置不夠則換到下(xià)一行,如果水(shuǐ)平位置和(hé)垂直位置都還(hái)有剩,則會優先往上放。
浮動元素與父元素、浮動元素之間的(de)内外邊界不會相交。也(yě)就是說,浮動元素以及其父元素的(de)padding、margin區(qū)域都不會重疊。
浮動元素的(de)頂邊不會超過源代碼中它前面出現元素所生成行框的(de)頂。
幾乎所有關于浮動布局可(kě)能出現的(de)問題,都可(kě)以在上面這(zhè)幾條中找到原因。舉個(gè)栗子:兩列布局
微博就是最典型的(de)兩列布局(新版V6的(de)登錄後首頁變成三列了(le),不過用(yòng)戶頁面仍然是兩列…),這(zhè)種兩列式的(de)布局解決方法很簡單,兩個(gè)固定寬度的(de)div,一起向左浮動,或者一個(gè)向左、一個(gè)向右。
而在很多(duō)遊戲網站中,爲了(le)盡可(kě)能利用(yòng)大(dà)屏幕的(de)優勢,而把頁面設計成左邊有一個(gè)固定寬度的(de)導航,右側全屏占滿,在這(zhè)種情況下(xià),上面的(de)寫法就不成立了(le)。不管兩個(gè)元素如何浮動,寬度都沒有辦法正好撐滿整個(gè)屏幕,雖然 CSS 中的(de)width(寬度) 屬性可(kě)以使用(yòng)百分(fēn)比的(de)值,但是當你将其設爲100%的(de)時(shí)候,它又掉下(xià)來(lái)了(le)。此時(shí)最好的(de)做(zuò)法是将左邊欄(第一個(gè) div)設爲浮動,并且給一個(gè)固定的(de)寬度(比如200px)。此時(shí)兩個(gè) div 元素在同一高(gāo)度上,但是右側的(de) div 看不到左側的(de)那個(gè),内容仍然從左上角開始顯示,此時(shí)隻要給這(zhè)個(gè) div 的(de)margin-left賦值爲200px,就可(kě)以将右側div的(de)左邊200px空出來(lái),這(zhè)樣兩列布局的(de)基本就完成了(le)。
清除浮動(Clear-fix)
有些人(rén)覺得(de)Clear fix被翻譯爲清除浮動并不合适,因爲實際上浮動仍然還(hái)在(元素仍然漂浮著(zhe)),而這(zhè)個(gè)術語的(de)本意也(yě)應該是“清除浮動所造成的(de)不良影(yǐng)響”,不過在中文圈子裏,從 clearfix 方法出生伊始,它就被叫做(zuò)清除浮動了(le)…所以也(yě)沒辦法啦╮(╯▽╰)╭。
它所修正的(de)不良影(yǐng)響,主要是針對(duì)上面的(de)第二條。浮動元素的(de)父元素看不到它:如果某個(gè)塊級元素裏的(de)所有子元素都是浮動的(de),那麽這(zhè)個(gè)元素自身就不會有高(gāo)度,在需要設置背景和(hé)邊框的(de)時(shí)候,這(zhè)種問題總像幽靈般如影(yǐng)随形。解決方法也(yě)很成熟:
另外還(hái)有一個(gè)“真正的(de)”清除屬性——clear,在上面的(de)示例中也(yě)出現了(le),這(zhè)個(gè)屬性規定了(le)該元素的(de)左側或右側是否可(kě)以與浮動元素相鄰——如果規定的(de)方向有浮動元素,那麽這(zhè)個(gè)元素就會向下(xià)排列(到底是有多(duō)討(tǎo)厭人(rén)家…)
絕對(duì)定位
還(hái)有一種比較特殊的(de)定位方式,被稱爲絕對(duì)定位,事實上我們PS文件中的(de)圖層都是絕對(duì)定位。position:absolute的(de)元素就成爲了(le)一個(gè)絕對(duì)定位元素,相對(duì)定位是相對(duì)于元素自身,而絕對(duì)定位也(yě)是針對(duì)元素自身而言——跟自身原本絕對(duì)沒關系。
絕對(duì)定位的(de)元素完全脫離了(le)常規流,可(kě)以說是“哪個(gè)元素都看不見它”。而它仍然需要一個(gè)定位的(de)“原點”,W3C規定離絕對(duì)定位元素最近的(de)position屬性爲relative、absolute或fixed的(de)祖先元素的(de)内容框的(de)左上角(有一個(gè)特例,就是該祖先元素爲行内元素的(de)時(shí)候,這(zhè)裏不展開說明(míng)了(le),基本遇不到),作爲該元素絕對(duì)定位的(de)原點。因此,其實,相對(duì)定位元素(position:relative)通(tōng)常都被用(yòng)于創建絕對(duì)定位元素的(de)包含塊(containing block),如果你有一個(gè)絕對(duì)定位元素,而它的(de)位置跟你預想的(de)不對(duì),那就是其定位基準出問題了(le)。而其定位方式一樣,是通(tōng)過上下(xià)左右的(de)值來(lái)規定的(de)。
固定定位
position:fixed的(de)元素就是固定定位元素,本質上它也(yě)是一種絕對(duì)定位,這(zhè)種元素會固定于浏覽器窗(chuāng)口的(de)固定位置,很多(duō)網站頂端的(de)固定導航、右下(xià)角的(de)固定廣告等等都是通(tōng)過這(zhè)種方式定位的(de)。
定位關系
如果某個(gè)元素是絕對(duì)定位元素(position爲absolute或fixed),則float屬性對(duì)其無效,同時(shí)元素變爲塊級元素。
而當某個(gè)元素的(de)position不爲static(position:static即爲最普通(tōng)的(de)常規流中的(de)元素)時(shí),它們彼此之間就有可(kě)能發生重疊(就像PS圖層一樣,圖層重疊是很常見的(de))。
在源代碼中後出現的(de)元素會覆蓋先出現的(de)元素
浮 動元素會覆蓋常規流元素
絕對(duì)定位元素會覆蓋浮動元素
使用(yòng)z-index可(kě)以無視上述三條規則z-index屬性可(kě)以規定圖層之前的(de)層疊順序,其數值越大(dà),該元素越靠“前”(疊在所有圖層的(de)最上面),如果你發現某個(gè)元素無論如何都覆蓋不了(le),檢查一下(xià)它的(de)z-index屬性值,也(yě)許就能找到答(dá)案。
Flexible Box(伸縮盒模型)
display:flex的(de)元素就會應用(yòng)伸縮盒模型,它是 CSS 中真正爲布局而生的(de)模型。現在關于這(zhè)個(gè)模型的(de)相關文章(zhāng)還(hái)很少,而且各種問題也(yě)很多(duō),因爲從09年到現在,它經曆了(le)3個(gè)大(dà)的(de)版本變化(huà),而這(zhè)涉及到了(le)大(dà)量手機及IE的(de)版本兼容問題,導緻很多(duō)網站都不願意采取這(zhè)種布局方式。
使用(yòng)這(zhè)種模型布局進行布局最炫酷的(de)一點是,我們不用(yòng)再費力計算(suàn)寬度然後爲元素規定寬度,所有的(de)寬度根據所有可(kě)用(yòng)空間及内容進行分(fēn)配,這(zhè)樣對(duì)于個(gè)數不固定的(de)元素也(yě)可(kě)以實現完美(měi)分(fēn)配。空間分(fēn)配方式有兩種:
按照(zhào)盒的(de)寬度比例分(fēn)配
按照(zhào)剩餘空間比例分(fēn)配
如果上面的(de)說明(míng)有點不清楚,點這(zhè)裏有一個(gè)DEMO,可(kě)以通(tōng)過改變左邊各項屬性的(de)值看到其結果。如果你們的(de)項目隻針對(duì)最新的(de)iPhone(iOS7及以上),你可(kě)以考慮拗你們的(de)前端去嘗試使用(yòng)這(zhè)個(gè)模型來(lái)布局(我曾親測過絕大(dà)多(duō)數網上流傳的(de)兼容代碼,全軍覆沒,主要國内有UC浏覽器這(zhè)個(gè)大(dà)殺器)。
後
display規定了(le)該元素所應用(yòng)的(de)模型,position規定了(le)該元素的(de)定位方式,二者共同構成了(le) CSS 定位與布局的(de)基礎。另外W3C也(yě)提出了(le)伸縮盒模型用(yòng)于滿足複雜(zá)多(duō)變的(de)布局需求,并且開始推薦廠商實現,如果各位有需要,在将來(lái)我可(kě)以單獨開一篇文章(zhāng)講這(zhè)部分(fēn)内容。