CSS原理解析之模型篇

寫在前面:

嘗試回答幾個問題:

  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. 最基本的例子

示例代碼

2. 當em變成absolute定位

示例代碼

盒模型

Margin

  1. 寬度。分為四個方向,都支持百分比和具體的像素。並且margin的百分比是根據元素的包含塊(containing-block)的width來計算。並不是margin-top/ bottom對應height。示例代碼
  2. 內聯元素(display: inline)的margin-top和margin-bottom失效。瀏覽器不允許設置。
  3. 合併。
    1. 水平的margin不會合併(inline-block和inline都支持) 示例代碼
    2. 都屬於常規流內(in flow)塊級盒,處於同一個上下文的兄弟元素 解決方法:將其中一個塊盒變成BFC,阻止margin的合併 示例代碼
    3. 塊級父元素和其子元素,在沒有padding,border,height,空隙將之隔開時,子元素的margin會滲透到父元素上。簡單講,父元素和子元素之間沒有其他元素。示例代碼
  4. 允許設置負值。
    1. 對於position=static元素,負值相當於將元素向負值方向移動覆蓋,但是只會覆蓋顏色,不會覆蓋文字。示例代碼
    2. 對於position=relative元素, 負值還是會把下面的元素粘著一起移動,但會完全覆蓋前一個元素。示例代碼
    3. 對於position=absolute元素,因為元素脫離了文檔流,所以負值只會自己發生偏移,對前後元素沒有任何影響。示例代碼
    4. 對於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. 非內聯元素百分比設置(見上文包含塊)
    1. 根據包含塊的content box寬度計算
    2. 如果當前元素是絕對定位,那麼相對父元素的padding box的寬度定位

Height

計算方式同width

定位模式

常規流

流內元素有幾大模型。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(四選一)
    1. 浮動
    2. 絕對定位
    3. 非塊盒的塊容器(inline-block)
    4. overflow不為visible的塊盒
  2. 特性
    1. 從包含塊頂部豎直方向排列
    2. BFC內部兄弟盒子之間的margin會合併——可以通過把兄弟之一變成BFC解決合併
    3. BFC可以阻止margin合併

IFC(Inline formatting contexts)內聯格式化上下文

  1. 如何產生:只有在一個塊級元素中僅僅包含內聯級別元素時才會生成
  2. 特性
    1. 從包含塊頂部水平方向排列
    2. 排列情況和浮動與否會改變行盒的高度
    3. 當一個行盒被分割,margin,border,padding都不會再有視覺效果了

浮動

  1. 概念:float CSS屬性指定一個元素應沿其容器的左側或右側放置,允許文本和內聯元素環繞它。該元素從網頁的正常流動中移除,儘管仍然保持部分的流動性
  2. 位置:
    1. 當一個元素浮動之後,它會被移出正常的文檔流,然後向左或者向右平移,一直平移直到碰到了所處的容器的邊框,或者碰到另外一個浮動的元素
    2. 浮動元素會根據上一個元素的類型判斷位置,如果上一個是浮動的,則跟隨他,放不下就擠到下一行
    3. 如果上一個是標準流的元素,則浮動元素的相對垂直高度不變,頂部和上一個元素的底部對齊。
  3. 清除浮動
    1. 引入空隙,父元素使用::after偽元素
    2. 浮動元素限制成BFC,使用overflow:hidden
    3. 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值 —— 定位元素。 層疊上下文中的最高等級。

當對某一個元素的z-index賦值了除了auto以外的值,就創建了一個新的層疊上下文,獨立於其他的層疊上下文。

比較順序變成,先比較各個層疊上下文的z-index。然後在層疊上下文中比較子元素的優先順序。

總結

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

推薦閱讀:

詳解 CSS 七種三欄布局技巧
為響應式web設計創建媒體查詢
[譯] 使用 CSS 的 font-size-adjust 屬性改善網頁排版
鵝廠原創 | 純 CSS 實現波浪效果
「投稿」「朝令夕改」,Google 終拒 Adobe Web 發布技術

TAG:前端开发 | CSS布局 | CSS |