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