CSS原理解析之模型篇

美團點評點餐發表於2017-10-10

寫在前面:

嘗試回答幾個問題:
  1. 什麼是盒模型,控制盒模型的屬性有哪些?
  2. Margin、Padding、Border、Width、Height這些屬性改變/影響盒模型,但每個屬性都會在所有元素上生效麼?
  3. 如果存在區別,那麼和元素型別或者元素定位有關係麼?
  4. 浮動元素是什麼?位置如何確定?如果去掉浮動?
  5. 層疊關係如何判斷優先順序?越大就越靠近使用者麼?
盒模型是我們每天都在接觸的,但盒子模型到底如何計算排列的,總是一知半解。本文嘗試從W3C規範和例項入手,解決上述問題。

目錄

包含塊(containing block)
盒模型(Box model)
定位模式(Positioning schemes)
層疊關係(Layered presentation)

包含塊

概念
每個盒子會變成他後代盒子的包含塊,後代盒子的大小和位置會根據他包含塊的矩形邊框進行計算。但是不會受到包含塊的限制,可能會溢位。
確定包含塊的方法
  1. 對於根元素、position=fixed的元素,包含塊都是視窗
  2. 如果元素是relative或者static,則是他最近的塊形父元素的內容區(content)——注:規定了父元素必須是block container
  3. 如果元素是absolute,包含塊是最近的非static的父元素的Padding區——注:父元素的型別未規定
舉例
包含塊最直觀的判斷是一個元素對大小設定百分比時,相對的元素是哪一個,這個元素就是他的包含塊
1. 最基本的例子
CSS原理解析之模型篇
2. 當em變成absolute定位
CSS原理解析之模型篇

盒模型

Margin
  1. 寬度。分為四個方向,都支援百分比和具體的畫素。並且margin的百分比是根據元素的包含塊(containing-block)的width來計算。並不是margin-top/ bottom對應height。示例程式碼
  2. 內聯元素(display: inline)的margin-top和margin-bottom失效。瀏覽器不允許設定。
  3. 合併。
    • 水平的margin不會合並(inline-block和inline都支援) 示例程式碼
    • 都屬於常規流內(in flow)塊級盒,處於同一個上下文的兄弟元素 解決方法:將其中一個塊盒變成BFC,阻止margin的合併 示例程式碼
    • 塊級父元素和其子元素,在沒有padding,border,height,空隙將之隔開時,子元素的margin會滲透到父元素上。簡單講,父元素和子元素之間沒有其他元素。示例程式碼
  4.  允許設定負值。
    • 對於position=static元素,負值相當於將元素向負值方向移動覆蓋,但是隻會覆蓋顏色,不會覆蓋文字。示例程式碼
    • 對於position=relative元素, 負值還是會把下面的元素粘著一起移動,但會完全覆蓋前一個元素。示例程式碼
    • 對於position=absolute元素,因為元素脫離了文件流,所以負值只會自己發生偏移,對前後元素沒有任何影響。示例程式碼
    • 對於float元素,可以通過負值進行覆蓋,最常見的應用是三欄應用。示例程式碼
Padding
  1. 寬度。同Margin。
  2. 內聯元素(display: inline)的padding生效,但是top和bottom並不會推擠,只會覆蓋其他元素,覆蓋情況遵循z-index原則。示例程式碼
  3. 合併。Padding不存在合併情況示例程式碼
  4. 不允許負值。
Border
  1. 寬度。只有px,不支援百分比。
  2. 合併。inline元素左右不合並,上下會合並。inline-block&block元素四個方向都不會合並示例程式碼
Width
  1. 內聯元素不能設定width和height。
  2. 非內聯元素百分比設定(見上文包含塊)
    • 根據包含塊的content box寬度計算
    • 如果當前元素是絕對定位,那麼相對父元素的padding box的寬度定位
Height
計算方式同width

定位模式

常規流
CSS原理解析之模型篇
流內元素有幾大模型。CSS2.1中定義了IFC(Inline Formatting Contexts)與 BFC(Block Formatting Contexts)。CSS3中增加了GFC(GridLayout Formatting Contexts)和FFC(Flex Formatting Context)。後兩個後續文章會詳細講解,這裡暫且不提。
BFC(Block formatting contexts)塊格式化上下文
  1. 什麼情況產生BFC(四選一)
    • 浮動
    • 絕對定位
    • 非塊盒的塊容器(inline-block)
    • overflow不為visible的塊盒
   2. 特性
    • 從包含塊頂部豎直方向排列
    • BFC內部兄弟盒子之間的margin會合並——可以通過把兄弟之一變成BFC解決合併
    • BFC可以阻止margin合併
IFC(Inline formatting contexts)內聯格式化上下文
  1. 如何產生:只有在一個塊級元素中僅僅包含內聯級別元素時才會生成
  2. 特性
    • 從包含塊頂部水平方向排列
    • 排列情況和浮動與否會改變行盒的高度
    • 當一個行盒被分割,margin,border,padding都不會再有視覺效果了
浮動
  1. 概念:float CSS屬性指定一個元素應沿其容器的左側或右側放置,允許文字和內聯元素環繞它。該元素從網頁的正常流動中移除,儘管仍然保持部分的流動性
  2. 位置:
    • 當一個元素浮動之後,它會被移出正常的文件流,然後向左或者向右平移,一直平移直到碰到了所處的容器的邊框,或者碰到另外一個浮動的元素
    • 浮動元素會根據上一個元素的型別判斷位置,如果上一個是浮動的,則跟隨他,放不下就擠到下一行
    • 如果上一個是標準流的元素,則浮動元素的相對垂直高度不變,頂部和上一個元素的底部對齊。
   3. 清除浮動
    • 引入空隙,父元素使用::after偽元素
    • 浮動元素限制成BFC,使用overflow:hidden
    • clear屬性
   4. 程式碼:示例程式碼
絕對定位
position=absolute設定元素絕對定位,會導致元素變成絕對定位,脫離文件流,並且元素此時是BFC佈局,Margin不會進行合併。使用top/bottom/left/right(下面簡寫成TBLR)控制位置的變動,具體畫素和百分比都參照包含塊進行偏移。
比較其他position屬性值
  1. position=static 常規流佈局,無法通過TBLR控制位置
  2. position=relative 盒子相對於其常規流位置進行偏移,兄弟元素相對其偏移前的位置定位。使用TBLR控制時,如果是固定畫素,那盒子相對於自身邊界偏移,如果是百分比,則參照包含塊偏移。
  3. position=fixed 包含塊是視窗,使用TBLR控制都是相對包含塊偏移
  4. 對於百分比:left/right 相對於包含塊的width,top/bottom相對於包含塊的height

層疊關係

在一個層疊上下文中一共可以有7種層疊等級,列舉如下:示例程式碼
  1. 背景和邊框 —— 形成層疊上下文的元素的背景和邊框。 層疊上下文中的最低等級。
  2. 負z-index值 —— 層疊上下文內有著負z-index值的子元素。
  3. 塊級盒 —— 文件流中非行內非定位子元素。
  4. 浮動盒 —— 非定位浮動元素。
  5. 行內盒 —— 文件流中行內級別非定位子元素。
  6. z-index: 0 —— 定位元素。 這些元素形成了新的層疊上下文。
  7. 正z-index值 —— 定位元素。 層疊上下文中的最高等級。
CSS原理解析之模型篇
當對某一個元素的z-index賦值了除了auto以外的值,就建立了一個新的層疊上下文,獨立於其他的層疊上下文。
比較順序變成,先比較各個層疊上下文的z-index。然後在層疊上下文中比較子元素的優先順序。

總結

  1. 本文解釋包含塊,以及基於包含塊確定的盒模型,對盒模型的四個邊界的計算方式做了總結。
  2. 對元素的定位方式和不同定位方式引起的元素之間位置變化做了總結。
  3. 後續會繼續以總結形式梳理CSS中常見但迷惑的地方。
  4. 如有錯誤,請指出,大家一起共同進步~



相關文章