前端css佈局知識繁雜,實現方式多種多樣。想寫出高效、合理的佈局,必須以深厚的css基礎爲前提。爲了方便記憶和複習,將css佈局要點記錄以下。內容較多,應用方面說的不太詳細,但都是很實用的點。css
所謂佈局,就是指將元素設置爲咱們想要的大小,放置於咱們想要的位置,位置
、尺寸
是核心兩要素。這些元素其實就是一些方塊,頁面就是由各類方塊拼湊而成。如今佈局方式主要分爲三種:html
使用哪一種佈局方式,看項目具體要求,若是不須要兼容IE,建議使用flex或者grid,這兩種是將來趨勢。若是要考慮兼容,則最好使用傳統css佈局方案。前端
前面提過,一個html元素,就是一個方塊,講究一點的話就是盒模型。盒模型長這樣:chrome
咱們能夠在chrome開發者工具的styles中查看:瀏覽器
css盒模型,分爲4部分:ide
無規矩不成方圓。全部的html元素都是按照必定規則去排列渲染的。在html中,不僅有一種規則,是多種規則的混合。瞭解這些渲染規則和這些規則生效的條件對於咱們理解css有很大幫助。工具
文檔流能夠理解爲全部元素的默認渲染規則。它的規則很簡單:元素按照本身的類型
的佈局特性從左到右,從上往下依次排列。佈局
元素在佈局上分爲三種類型:字體
上面內聯元素其實說的不太正確,這裏須要特殊說一下,內聯元素又分爲兩種:flex
有兩種方式能夠脫離文檔流,絕對定位和浮動,咱們下面再詳細說。
BFC全稱是Block Formatting Context,塊級格式化上下文。在BFC環境中的元素按照以下規則渲染:
類型
的佈局特性從左到右,從上往下依次排列。那麼什麼樣的渲染區域是一個BFC哪?下列幾種方式能夠顯示聲明一個BFC的渲染區域:
元素的尺寸有兩種狀況:
咱們先來明確一下元素的尺寸概念,咱們都知道元素的盒模型,元素由content、padding、border、margin四個區域組成。那麼尺寸具體是指什麼?咱們能夠把尺寸分爲三類:
而咱們在css中設置的width、height表明哪部分區域是有歧義的,咱們經過設置box-sizing,能夠切換width、height所表明的區域。
box-sizing,能夠切換width、height所表明的區域。box-sizing主流瀏覽器有兩個值:
box-sizing的這兩個屬性,形成width、height的二義性,並且不少狀況下是全局設置的,隱蔽性很強,對於新手來講很容易懵。這兩個屬性的產生有必定的歷史緣由,最開始的盒模型默認採用的border-box,早期的IE就是這種,也叫IE盒模型。後來W3C以爲content-box更好,又把盒模型默認改成content-box模式。後來的後來,隨着彈性佈局的流行,border-box的優點愈來愈明顯,你們都更願意使用border-box來佈局,W3C又想把border-box搞回來。可是已經有好多基於content-box的網站,爲了兼容性也不能隨便改。因而,W3C就想出了box-sizing這種方式,支持了border-box,可是默認仍是content-box。使用box-sizing應注意的幾點:
設置全部元素的box-sizing屬性爲inherit:
*, *:before, *:after { box-sizing: inherit; }
這樣咱們能夠設置父元素的box-sizing,就能夠控制全部子元素的box-sizing屬性,對於咱們封裝組件,設置整個組件環境很方便,只有咱們在封裝組件時強設置box-sizing,就不怕全局的樣式侵入了。
咱們知道width, height都是能夠設置百分比,那這個百分比的參照物是誰?這裏引出一個概念,叫作包含塊(CB, Contanining Block),一個元素的包含塊就是該元素的width、height百分比的參照物。
不少新手同窗,在設置寬高百分比的時候,有時候以爲莫名其妙,各類奇怪現象,怎麼設置都不起做用。其實就是沒有包含塊的概念。一個元素的包含塊是誰,主要取決於該元素的position屬性,總結以下:
position爲absolute和fixed時,包含塊也多是由知足如下條件的最近父級元素的padding-box:
這條比較特殊,遇到的狀況比較少,單獨拿出來
除了width, height的百分比相對於包含塊設置外,margin、padding的百分比也是相對於包含塊設置,只不過margin、padding百分比相對於包括塊的寬度設置(水平模式下)。絕對定位的偏移屬性top、left、right、bottom也是相對於包含塊設置,後面再詳細說。
元素的包含塊都是本身的祖先元素,那hmtl
元素沒有祖先元素,它的百分比設置相對於誰那?就是初始包含塊,根元素(hmtl
)所在的包含塊是一個被稱爲初始包含塊的矩形。這個矩形的大小就是瀏覽器視口的大小。有一點須要注意,那些沒有定位非static祖先元素的參照物是初始包含塊,而非html元素。
由於margin在佈局中有一些重要特性和特殊狀況,因此單獨拿出來說一下。
咱們知道,塊級元素即便設置了寬度,也會佔滿一行,爲何會這樣?剩餘的空間被誰佔了?
這裏要明確一點,塊級元素佔據一行,是指塊級元素的外部尺寸佔據一行,就是margin-box。當margin設置爲auto的時候,margin會自動佔滿剩餘空間。
當margin-left和margin-right同時爲auto,就會平分剩餘空間,這就是margin:auto
會使元素水平居中的緣由。而後margin: auto
卻不能使元素垂直居中,這是由於在垂直方向上,塊級元素不會自動擴充,它的外部尺寸沒有自動充滿父元素,也沒有剩餘空間可說。若是咱們在父元素上設置writing-mode: vertical-lr
,這時margin:auto
就會使子元素垂直居中,而水平居中無效。
那有沒有什麼辦法使用margin:auto
讓元素同時水平垂直居中?答案是有的,就是絕對定位的狀況下。
.father { width: 300px; height:150px; position: relative; } .son { position: absolute; top: 0; right: 0; bottom: 0; left: 0; width: 200px; height: 200px; margin: auto; }
此時的son的外部尺寸,就會自動充滿它的包含塊,效果和塊級元素相似。這時候設置.son元素的寬高,就會有剩餘空間出來,margin:auto
會自動平分剩餘空間,使.son水平垂直居中。
margin對元素的影響有2個:
塊級元素這種寬度方向自動充滿空間的佈局特性,當沒有設置寬度,設置margin-left和margin-right爲對元素的內部空間有影響。margin爲正值時,元素尺寸
縮小;margin爲負值時,元素尺寸
增大。由於元素的外部尺寸大小已經定了,就是其包含塊的尺寸,而外部尺寸
等於元素尺寸
加上margin,若是margin爲負,元素尺寸
天然就增大了。利用內部尺寸增大、外部尺寸不變這個特色,咱們能夠進行等間隔列表的佈局。好比咱們實現一個一行三列,兩側無間隙,中間間隙爲20px的佈局:
.father{ margin-right: -20px; } .son{ width: calc( calc(100% - 20px * 3) / 3); margin-right: 20px; }
在元素寬高固定的時候,至關於元素尺寸
固定了,margin開始影響元素的外部尺寸
。正margin會使元素元素的外部尺寸
增大,負margin會使元素元素的外部尺寸
縮小。正值很好理解,就不說了。主要說一下負值,這時候margin-top、margin-left和margin-right、margin-bottom的表現看起來是有區別的,實質是同樣。margin-top、margin-left爲負值時,表現爲元素向上或者向左移動,margin-right、margin-bottom爲負值時,表現爲其右側元素或者下面元素都會相應地向左或者向上移動。仔細想一想,這都是元素外部尺寸
縮小的表現。margin-top、margin-left使左側上上側尺寸縮小,就會天然向左或者向上移動。margin-right、margin-bottom使右側和下側尺寸縮小,旁邊和下面的元素天然就會往左或者往上佔位。
塊級元素的上邊距和下邊距在某些場景下會發生合併行爲。須要注意的是浮動元素和絕對定位元素不會發生合併,且合併只發生在垂直方向。有如下3中合併場景
margin合併的計算規則
阻止margin合併的方法
主要想說line-height
,vertical-align
兩個屬性,這兩個屬性對高度有重要的影響,並且若是沒有理解這兩個屬性的做用,會常常碰到一些很差解決的詭異的佈局問題。
這個名字是張鑫旭大神定義的,在W3C規範中也是能夠找到根據的。在《CSS世界》這本書中,爲了證實幽靈空白節點的存在,舉了一個例子:
div { background-color: #cd0000; } span { display: inline-block; } <div><span></span></div>
你可能猜到了,div的高度不爲0,我在chrome下試了試高度爲21px,這個高度猜想應該和div的字體、字體大小、行高有關。這個幽靈空白節點的存在,會引發一些怪異現象,好比:
<div><img></img></div>
div的高度老是比img高一些,img下總有一個間距。這也是一個幽靈空白節點在起做用。
line-height翻譯過來就是行高。它指的是指行框
的高。那什麼是行框
那?
行框是由內聯元素或者內聯塊級元素組成的一行。經過嘗試,發現一行造成行框的兩個前提是,要麼有文字內容,要麼有內聯塊級元素,若是其中是一堆空的內聯元素,好比span,是沒有造成行框的。
line-height就是指定行框佔據的高度。只有造成了行框,line-height纔會起做用。
這裏可能有一些容易誤解的狀況,好比:
.father{ line-height: 300px; } <div class="father"> <div class="son"> 你好 </div> </div>
這時候.fahter高度是300px,這裏注意的是,不是line-height對.son起做用了,是.son內部造成了一個行框,line-height對這個行框起做用了,.son的高度是300px,撐開了.father。
vertical-align用來設置內聯元素或者內聯塊級元素在行框內的對齊方式或者說垂直位置。verticle-align有四類值,咱們在這裏直說其中對佈局比較重要的兩類:
先來看一張圖:
vertical-align默認是基線對齊的,基線的位置很重要。而基線的定義是:字母x的下邊緣
。中線的位置是基線往上 1/2 x-height 高度,就是x交叉的地方。這裏有一個須要注意的地方是,純文字的中線是x交叉的地方,可是內聯元素的中線倒是內聯元素的正中間位置。咱們來看一個例子:
div{ line-height: 100px; background: yellow; } <div> <span class="world">xhello</span> </div>
效果以下:
一切正常,div高度100px,文字也是近似垂直居中。可是若是咱們在.world元素上加vertical-align: middle
,咱們會發現文字向下偏移,且div高度變成了102px,效果以下:
這是怎麼回事那,vertical-align設置的到底跟誰對齊?答案是幽靈空白節點,幽靈空白節點是個很神奇的存在,看不見,但卻實實在在地在起做用,它的做用就至關於一個x字符的做用,用來提供對齊基準。咱們上面說到的,div元素中有一個圖片的例子,img是可替換內聯元素,它的baseline就是它的底部,默認是baseline對齊,因此圖片對齊的是幽靈空白節點x的基線,x基線位置往下是一段空白的,這就是這段空白的來源。爲了更直觀,咱們在上面這個例子的span元素前面加一個x字符,當作幽靈空白節點,看一下效果:
原本,x
和xhello
中的x
是對齊的。設置vertical-align以後,咱們能夠看到xhello字符向下挪了一段位置,這是由於span元素的垂直中線位置,比xhello
中x
交叉點要高,如今要和前面的x
交叉點對齊,就往下移動了。又由於x
和xhello
的行高都是100px,可是如今由於因爲錯位,形成總體高度多了2px。
利用line-height和vertical-align能夠設置多種場景下的垂直居中。
div{ line-height: 任意值 } <div>hello world</div>
.box { line-height: 120px; background-color: #f0f3f9; } .content { display: inline-block; line-height: 20px; margin: 0 20px; vertical-align: middle; } <div class="box"> <div class="content">多行文字...</div> </div>
.container { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background-color: rgba(0,0,0,.5); } .container:after { content: ''; display: inline-block; height: 100%; vertical-align: middle; } .dialog { display: inline-block; vertical-align: middle; } <div class="container"> <div class="dialog"></dialog> </div>
元素的位置由position屬性和float屬性決定。
position有4個值:
須要注意的地方有:
float屬性可使元素脫離文檔流,向左或者向右移動,直至碰到包含塊的padding或者碰到另外一個浮動元素。注意:
float最著名的就是它的高度坍塌,之因此有高度坍塌,和float設計的初衷有關。float屬性最初是設計用來實現文字環繞效果的。
<div class="img-wrap"> <img style="float: left"/> </div> <p>我是文字,我要環繞你</p>
.img-wrap由於高度塌陷,實際上不識別float元素,高度爲0,p元素與其重合,從而實現文字環繞效果。
高度塌陷特性在實現佈局的時候是不合理的,而如今文字環繞的場景不多,float基本都用來佈局使用了。這如今實際上已經成爲了一個「bug」的存在。因此css又提供了一個屬性用來清除浮動:clearfix。
clearfix在mdn上的解釋爲指定一個元素是否能夠在它以前的浮動元素旁邊(我以爲這裏用重合更貼切),或者必須向下移動(清除浮動) 在它的下面。
注意上面這句話,指定一個元素
表示clearfix的做用目標是元素自身,在它以前的浮動元素
表示clearfix的做用條件是它前面有浮動元素,而clearfix的做用效果是讓元素換行顯示。因此clearfix的做用是,若是元素前面有浮動元素,能夠指定該元素換行顯示,或者說是識別前面的浮動元素。clearfix有3個值:
通常狀況下采用clearfix: both。清除浮動一個重要應用就是解決float高度塌陷的問題。通用的解決方案是設置.clearfix類:
.clearfix { display: block; zoom: 1; &:after { content: ""; display: block; font-size: 0; height: 0; clear: both; visibility: hidden; } }
在包含浮動元素的父元素上設置該類便可。