深刻理解css盒子模型

css是一門具象語言,並不像js那樣具備邏輯性,所以,就算入行了前端好久的工程師,也以爲css難以掌握。下面咱們就一步一步揭開css的神祕面紗,深刻理解css盒模型,這對咱們在佈局上會有一個質的提高。css

盒子模型

圖片描述
相信不少人對這幅圖都不陌生,盒子模型簡單點理解就是外邊距(margin)+邊框(border)+內邊距(padding)+內容(content),頁面所呈現的效果其實就是一個個盒子堆疊而成的。每個元素實際上是包含了一個「外在盒子」和一個「內在盒子」,其中「外在盒子」負責元素是一行顯示仍是換行顯示,而「內在盒子」則負責寬高、內容展示。咱們都知道inline-block(inline對應於「外在盒子」,block對應於「內在盒子」),而block能夠簡單地理解爲block-block,table爲block-table(由於還有一個inline-table)。html

內聯盒模型

  • 內容區域(content area)
  • 內聯盒子(inline box)
  • 行框盒子(line box)
  • 包含盒子(containing box)

內容區域(content area)。內容區域指的是一種圍繞文字看不見的盒子,其大小僅受字符自己特性控制,本質上是一個字符盒子(character box);可是圖片這樣的替換元素,其顯示內容不是文字,所以內容區域能夠當作是元素自身。 前端

內聯盒子(inline box)。「內聯盒子」不會讓內容成塊顯示,而是排成一行,這裏的內聯盒子指的是元素的「外在盒子」,用來決定元素是內聯仍是塊級。該盒子又能夠細分爲「內聯盒子」和「匿名內聯盒子」。以下:
圖片描述css3

行框盒子(line box)。每一行就是一個行框盒子,每一個行框盒子都是由一個個內聯盒子組成,注意:line-height是做用在行框盒子上的,並最終決定高度(替換元素除外,後面會講解什麼是替換元素)。canvas

包含盒子(containing box)。此盒子由一行一行的「行框盒子」組成(css規範中,並無「包含盒子」的說法,更準確的稱呼是「包含塊」(containing block)。瀏覽器

width

width的默認值是auto,但不少人卻都不理解這個值是什麼意思,由於auto在不一樣場景會有不一樣的表現:ide

  • fill-available
  • fit-content
  • min-content
  • max-content

fill-available:充分利用可用空間,例如div、p這些元素的寬度是默認100%於父級容器的。可是width: auto卻不一樣於width: 100%,這是不少人不理解的地方。若是你設置了width: 100%,這裏指的是內容區域100%,即css3中的content-box,這時若是你設置了padding、border或者margin,元素都會撐破父元素,從而破壞佈局。你固然能夠設置box-sizing: border-box,但惋惜的是css3中沒有margin-box,這時候你若是設置了margin,依然會撐破父元素,可是width: auto卻不會,以下所示:佈局

圖片描述

圖片描述

fit-content:收縮到合適,典型表明浮動、絕對定位(有例外,設置了對立屬性:left、right、top、bottom時,寬度和高度由祖先元素position非static的元素決定,可是替換元素除外:img、video、canvas等)、inline-block、table。利用這個特性咱們能夠實現,文字總體居中,多行則居左顯示,以下:字體

圖片描述

圖片描述

圖片描述

min-content:收縮到最小。在表格中最多見,當每一列空間都不夠的時候,文字能斷則斷,中文隨便斷,英文單詞不能斷。能夠根據這個特性實現凹凸圖形等效果,以下:spa

圖片描述

圖片描述

圖片描述

max-content:超出容器限制,內容很長的連續英文或數字,或者內聯元素被設置爲了white-space: nowrap。

圖片描述

圖片描述

圖片描述

height

height的默認值也是auto,指的是其高度由內部元素堆疊而成,內部元素盒子有多高,元素就有多高。但在絕對定位中,若同時設置了top與bottom,則其高度由父盒子高度減去top與bottom。

height: 100%。若是父元素height爲auto,則子元素height:100%是無效的,要想子元素height: 100%生效,則:

  • 父元素設定顯式高度值
  • 使用絕對定位(絕對定位元素的百分比是根據padding box計算的,非絕對定位元素百分比是根據content box計算的)

替換元素

因爲替換元素在不少表現上都與普通內聯元素不同,所以在這裏着重介紹一下替換元素。

  • 根據「外在盒子」是內聯仍是塊級,咱們把元素分爲內聯元素和塊級元素,而根據內容是否可替換,咱們把元素分爲可替換元素和非替換元素。
  • <img>,<video>,<canvas>,<input>,<textarea>,<iframe>都是替換元素。
  • 替換元素外觀不受頁面css的影響,有本身的尺寸,通常爲300 * 150,在不少css屬性上有本身的一套表現規則,例如vertical-align默認就是元素下邊緣對齊,而不是基線對齊。
  • 替換元素尺寸計算規則:css尺寸 > html尺寸 > 固有尺寸
  • 內聯替換元素和塊級替換元素規則一致,即display: block,其寬度也不會100%。
  • 替換元素固有尺寸沒法更改,width和height改變的是content-box的寬高,而默認替換元素的object-fit是fill,也就是會填充content-box,所以看上去像是改變了固有尺寸。
  • 替換元素before和after僞元素無效。

padding

  • padding與內聯元素
  • padding的百分比值

padding與內聯元素。padding做用在塊級元素上會影響盒子的寬高,可是若是做用在內聯元素上(不包括替換元素),彷佛就只能做用在水平方向上,垂直方向上就沒看到任何影響。但事實並非沒有影響,只是視覺上咱們以爲沒有影響而已。由於內聯元素沒有可視寬度和可視高度的說法(clientWidth和clientHeight永遠是0),垂直方向徹底受line-height和vertical-align的影響,視覺上並無改變上一行和下一行內容的間距,所以,給咱們的感受就是垂直方向上padding沒有起做用。利用這個特性,咱們能夠在垂直方向上增大可點擊區域,這樣既不會破壞現有佈局,也能很好地響應用戶的點擊。特別是在移動端,一個關閉的「x」若是過小,用戶就很難點擊到,調大字體又會影響佈局,這時候就能夠用到padding。

padding的百分比值。padding不支持負值,padding百分比不管寬高都是相對於width來講的,另外padding區域是跟着行框盒子走的。所以,若是padding做用於內聯元素,則寬度和高度細節有差別,而且padding會斷行,其緣由在於strut,意思是說每個行框盒子前面都有一個不可見的盒子,其line-height和font-size都繼承於父元素,稱爲strut。利用padding的這些特性,咱們能夠實現以下效果:

  • 利用padding實現一個正方形

圖片描述

圖片描述

圖片描述

  • 內聯元素padding高度差別(只需把font-size設爲0便可變爲正方形)

圖片描述

圖片描述

圖片描述

  • padding斷行(因爲padding做用在行框盒子上,所以文字換行,padding也跟着換行,後面的背景蓋住了前面的,就造成了這種效果)

圖片描述

圖片描述

margin

  • margin: auto
  • margin改變元素尺寸
  • margin負值
  • margin合併
  • margin無效的狀況

margin: auto生效的前提是元素在width和height爲auto的時候可以自動填充容器,這樣,在設置width或height的值時,若是還有剩餘尺寸,margin: auto就能夠利用剩餘尺寸。所以在絕對定位元素設置了top、bottom、left、right的狀況下,就能夠很方便地實現水平垂直居中,以下:

圖片描述

圖片描述

圖片描述

margin改變元素尺寸。在元素width爲auto的狀況下,margin正值和負值都能改變元素的尺寸。以下:

圖片描述

圖片描述

圖片描述

margin負值。margin支持負值,而且用途十分普遍,例如,在等寬的盒子中,最後一個元素不因margin-right而折行;實現等高佈局等。以下:

盒子並列佔滿父元素:

圖片描述

圖片描述

圖片描述

圖片描述

等高佈局,其原理是利用padding撐開一片足夠大的高度,再用margin負值將頂下去的元素收回來:

圖片描述

圖片描述

圖片描述

margin合併。塊級元素的上外邊距與下外邊距有時會合併爲單個外邊距,這種現象稱爲「margin合併」。通常會有如下三種:

一、相鄰兄弟元素margin合併

二、父級和第一個/最後一個子元素合併

margin-top合併,解決方案:

    父元素設置爲塊狀格式化上下文元素
    父元素設置border-top值
    父元素設置padding-top值
    父元素和第一個子元素之間添加內聯元素進行分隔

margin-bottom合併,解決方案:

    父元素設置爲塊狀格式化上下文元素
    父元素設置border-bottom值
    父元素設置padding-bottom值
    父元素和最後一個子元素之間添加內聯元素進行分隔
    父元素設置 height、min-height 或 max-height。

三、空塊級元素的margin合併,即自身有margin-top和margin-bottom,但元素是空的,此時會合併爲一個margin。

margin無效。margin在某些場景下會失效,但有些「失效」只是視覺上的表現而已。以下:

  • display 計算值 inline 的非替換元素的垂直 margin 是無效的,雖然規範提到有 渲染,但瀏覽器表現卻未尋得一點蹤影,這和 padding 是有明顯區別的。對於內聯替換元素, 垂直 margin 有效,而且沒有 margin 合併的問題,因此圖片永遠不會發生 margin 合併。
  • 表格中的<tr>和<td>元素或者設置 display 計算值是 table-cell 或 table-row 的元素的 margin 都是無效的。可是,若是計算值是 table-caption、table 或者 inline-table 則沒有此問題,能夠經過 margin 控制外間距,甚至::first-letter 僞元素也能夠解析 margin。
  • margin合併的時候,更改margin值可能無效。由於垂直方向上會發生margin合併。
  • 絕對定位元素非定位方位的margin值「無效」(其實margin是有效的,只是元素絕對定位了,並不影響其相鄰元素的渲染)。
  • 定高容器的子元素的margin-bottom或者寬度定死的子元素的margin-right的定位「失效」。這裏的失效也是假的,緣由跟絕對定位的margin無效相似,在一個默認流下,其定位方向是左側和上方,此時只有margin-left和margin-top能夠影響其定位,而margin-right和margin-bottom則只會影響其相鄰元素,若此時沒有相鄰元素,則看上去像是margin無效。
  • 內聯特性致使的margin值無效。一個div元素中有一個img圖片,咱們對img使用margin-top負值,當margin-top負值達到必定值的時候,再往上圖片也不會上移。

border

  • 製做圖形
  • 等高佈局

相信很多同窗都使用過border來製做圖形,例如三角形、圓形等等,此處就不舉例子,主要講講等高佈局,代碼和效果以下所示:

圖片描述

圖片描述

圖片描述

其原理就是父元素撐開一個border-left,菜單欄左浮動,而且寬度跟父元素border保持一致,經過margin-left負值往左偏移到border位置,另外父元素設置僞元素after來清除浮動,這樣就能夠實現左側固定,右側自適應的兩欄等高佈局。

參考資料:《CSS世界》

相關文章
相關標籤/搜索