前端布局基礎概述


一、 什么是前端布局基礎?
  前端布局方案主要有三種:
     傳統布局方案(借助浮動、定位等手段)
    flex布局方案
    grid布局方案
  這些方案都能夠解決布局問題,而且每個方案都有各自的理論基礎,那么哪一個方案的基礎理論可以稱得上是前端布局基礎?要回答這個問題,我們還得深入去了解這三種方案的特性。

   傳統布局方案,需要使用者熟練掌握元素的分類及布局特性、浮動原理和定位原理等眾多基礎知識,方能在解決各類前端布局問題時游刃有余,這不僅學習成本大,而且實現的復雜度也高,實現的CSS代碼也不夠精簡、優雅。但由於其基礎知識來源於CSS2,所以瀏覽器兼容性最好,對於用戶是友好的。

   flex布局方案,正是為了解決傳統布局方案的種種不便,而提出的一種新型改進方案,它不再需要借助浮動和定位等布局手段,而是通過父元素(flex box)單方面配置相關的CSS屬性來決定子元素的布局規則,且在大多情況下無需子元素(flex item)參與,就能完成子元素間的布局問題,不僅學習成本低(公司之前有幾個后端工程師亦能快速上手),且大大簡化了布局的實現復雜度,CSS代碼也更加精煉。美中不足的是IE10才開始支持,且需要使用-ms-前綴(IE11無需)。

  雖然現今的手機多使用的是現代瀏覽器,對flex支持度較好,然而並不是每一款手機都如此:筆者曾在一個移動端項目采用過flex布局方案,然而公司的測試同學在“華為榮耀5”的自帶瀏覽器,檢測到無法支持flex布局,我們能夠跟測試的同學說,是這款華為手機的瀏覽器有問題嗎?顯然不能。於是故筆者在項目早期就及時放棄了flex布局方案,改用傳統布局方案實現,避免了后面大規模的改動。

   grid布局方案,是由微軟提出,相對於傳統布局方案和flex布局方案,它是一種二維布局方案,在IE10開始支持,但需要使用-ms-后綴(IE11+不再需要)。

  總的來說,這三類方案都能基本解決日常的前端布局問題,且從易用性、靈活性和強大性來說,flex布局和grid布局更是未來的趨勢。但是從當前各版本瀏覽器在用戶市場上的使用情況和各方案的瀏覽器兼容性來看,傳統布局方案對用戶最友好,具有一定的不可替代性,所以我覺得,傳統布局方案是最應該先掌握好的,尤其是對於在to B企業工作的前端同學來說。
 
 二、布局基礎知識

  2.1. CSS標准盒模型(或W3C盒模型)
    一個web頁面是由眾多html元素拼湊而成的,而每一個html元素,都被解析為一個矩形盒,而CSS盒模型就是這種矩形盒的解構模型。CSS盒模型,它由內到外、被四條邊界Content edge、Padding edge、Border edge和Margin edge划分為四個區域:Content area、Padding area、Border area和Margin area,在形狀上,Content area(又稱content-box)是實心矩形,其余是空心環形(空心部分是Content area),如下圖所示:

                  CSS盒模型-區域划分圖

 此外,每個區域都有其特定的作用:Content area,是當前元素用來容納所有子孫元素;Padding area,是當前元素用來隔離自身和子孫元素;Border area是當前元素用來顯示自身的輪廓;Margin area,是當前元素用來隔離自身和相鄰元素。理解每個區域的作用和職責至關重要,有助於我們寫出優雅、清晰的布局代碼。 
   box-sizing(CSS3屬性)
    2.2.1. box-sizing的作用
      box-sizing,顧名思義,其作用與設置CSS box的尺寸大小有關,而CSS box又可細分為:
      content-box(即content area)
      padding-box(=content area + padding area)
      border-box(=content area + padding area + border area)
      margin-box(=content area + padding area + border area + margin area)
      簡單來說,box-sizing的作用就是告訴瀏覽器:CSS屬性width和height是用於設置哪一種box的尺寸,在W3C標准中,box-sizing的值僅有content-box和border-box(firefox則額外支持padding-box)。所以,
      當box-sizing的值為content-box(默認值)時,有:
        width = content-width;
        height = content-height;
      當box-sizing的值為border-box時,有:
        width = content-width + padding-left + padding-right + border-left-width + border-right-width;
        height = content-height + padding-top + padding-bottom + border-top-height + border-bottom-height;
    關於box-sizing的作用,還有另一種表述:告訴瀏覽器,是使用W3C盒模型,還是使用IE盒模型。

 

元素的分類及其布局特性

2.3.1. 元素的分類
  從元素的布局特性來分,主要可以分為三類元素:block-level(塊級)元素、inline-level(行內級)元素和inline-block-level(行內塊級)元素,我們可以對其下個定義:
   1   塊級元素
    display屬性取block、table、flex、grid和list-item等值的獨占一行顯示的元素。
   2   行內級元素
    display屬性取inline值的可在同一行內排列顯示的元素。
   3   行內塊級元素
    display屬性取inline-block、inline-table、inline-flex和inline-grid等值的兼具塊級元素和行內級元素布局特性的元素。

 
 2.4. 格式化上下文(Formatting Context)
格式化上下文,它指的是具有某種CSS格式化規則(布局規則)的上下文環境,在這個上下文環境內的所有子元素,都將根據其特定的CSS格式化規則來進行排列。

我們可以給某個作為容器的元素指定特定的格式化上下文,也就是說我們可以定義一個具有特定布局規則的渲染區域。常見的格式化上下文有BFC(CSS2.1 規范)、IFC(CSS2.1 規范)、 FFC(CSS3規范新增)和GFC(CSS3規范新增),具體介紹如下:
 
2.4.1. BFC
  BFC, 全稱是block formatting context,它是一個獨立封閉的渲染區域,在這個區域內的所有元素,從區域的頂部起,一個接一個地根據自身的布局特性進行排列:在這個區域內的塊級元素 ,按從上到下的順序顯示,相鄰的塊級元素可以使用margin隔離,但在垂直方向上相鄰的塊級元素會發生margin合並;在這個區域內的inline-level或inline-level-block元素,則按從左到右的順序顯示(W3C組織說BFC內部的元素都是一個接一個地垂直顯示,我覺得不是很嚴格,因為BFC內部也可以容納inline-level和inline-level-block元素,所以這里我的解釋和W3C還是稍微有一些不一樣)。具有BFC格式化環境的元素,我們稱之為BFC元素,可以說,BFC定義了BFC元素content區域的渲染規則。

看到這段描述,是不是覺得BFC的渲染規則,不就是文檔流的默認布局規則嗎?確實很像,但不完全等同。BFC元素內部的渲染規則和普通塊級元素內部的渲染規則,還是有一些不同的,我們將在5.4.1.3. 特性一節詳述。
 

2.4.1.2. 創建方式
創建BFC元素的方式有如下幾種(摘自MDN BFC):
  根元素或其它包含它的元素
  浮動元素 (元素的 float 不是 none)
  絕對定位元素 (元素的 position 為 absolute 或 fixed)
  內聯塊 (元素具有 display: inline-block)
  表格單元格 (元素具有 display: table-cell,HTML表格單元格默認屬性)
  表格標題 (元素具有 display: table-caption, HTML表格標題默認屬性)
  overflow 值不為 visible 的塊元素
  display: flow-root
  contain為以下值的元素: layout, content, 或 strict
  彈性項 (display: flex 或 inline-flex元素的子元素)
  網格項 (display: grid 或 inline-grid 元素的子元素)
  多列容器 (元素的 column-count 或 column-width 不為 auto, 包括 column-count: 1的元素)
  column-span: all 應當總是會創建一個新的格式化上下文,即便具有 column-span: all 的元素並不被包裹在一個多列容器中。

2.4.2. IFC
 定義
IFC, 全稱是inline formatting context,其內部的元素,在水平方向上,一個接一個地顯示;在垂直方向上,每個元素可以設置不同的對齊方式;IFC內部的元素,被一行行的矩形框所包含,這些虛擬的矩形框,我們稱為行框(line box)。IFC的作用區域,可以看成是包含其所有子元素的行框組成的矩形區域。

 創建方式
和BFC相比,它的創建方式是被動的、隱式的,是由所包含的子元素來創建:只有在一個區域內僅包含可水平排列的元素時才會生成,這些子元素可以是文本、inline-level元素或inline-block-level元素。

特性
1. IFC內部的元素,按從左到右、從上到下的順序排布;
2. IFC內部的每個元素,都可以通過設置vertical-align屬性,來調整在垂直方向上的對齊;
3. 包含這些內部元素的矩形區域,形成的每一行,被稱為line box(行框,后面會詳細介紹);

FFC和GFC
FFC(flex formatting context)和GFC(grid formatting context),分別是flex布局和grid布局的內容,這兩個模塊的內容非本文介紹的重點,所以感興趣的同學可以自行google。

包含塊(Containing Block)
   定義
我們在設置元素尺寸屬性(width、height、padding、margin和border)的百分比值或偏移屬性(top、right、bottom和left)的值時,通常會有一個“相對參考系”,這個"相對參考系"一般是包裹着這個元素的塊級祖先元素(一般是塊級父元素)或離這個元素最近的非static(relative、absolute和fixed)定位的祖先元素。這些具有“相對參考系”作用的祖先元素,其容納區域(cotent box或padding box),其實還有一個專門術語形容之,那就是包含塊(在知識體系中有個包含塊的概念,有助於加深對position定位原理的掌握)。

特別地,relative定位元素,其尺寸屬性(width、height等)的“相對坐標系”仍是其包含塊(塊級祖先元素(一般是父元素)的content box),但是偏移屬性(top、right、bottom和left)的“相對坐標系”則是其在文檔流原來的位置。

2.5.2. ICB(initial containing block, 初始包含塊)
 定義
如前面所說,任何一個元素都會有一個包含塊作為設置尺寸屬性和偏移屬性的“相對參考系”,而對於頂層的根元素<html />,沒有任何元素包裹它,它的包含塊是什么?它選取什么作為“相對參考系”?

其實根元素<html />是有包含塊的,它是一個不可見的矩形框,W3C組織稱之為ICB(initial containing block, 初始包含塊)。以下是W3C組織對ICB對定義:
The containing block in which the root element lives is a rectangle called the initial containing block.

ICB的尺寸和起始位置(左上角坐標)
在解釋ICB的尺寸和起始位置時,在這里先簡單補充一個背景知識:連續媒體(continuous media)和分頁媒體(paged media)。如何理解這兩個概念?在視覺閱讀層面,它們是展示內容的兩種呈現方式。

連續媒體,就是采用連續展示內容的方式,它保持了展示內容顯示的連續性(一頁顯示所有內容),我們可以在連續媒體的viewport(可視窗口)查看當前呈現的內容。特別地,瀏覽器窗口就可以看成是連續媒體,當內容的尺寸超過viewport時,讀者可以通過平滑滾動的方式來閱讀內容。

分頁媒體,就是采用切頁展示內容的方式,它將要展示的內容切分為等尺寸的多頁(分頁顯示所有內容),我們可以在分頁媒體的page area(頁面顯示區域)查看當前呈現的內容。特別地,像幻燈片、電子書閱讀器,就可以看成是分頁媒體,當內容的尺寸超過page area時,讀者可以通過切頁的方式來閱讀內容;

對於屬於連續媒體(continuous media)的瀏覽器窗口來說,ICB的尺寸為viewport(瀏覽器視窗),其起始位置為畫布原點(canvas origin,即首屏的左上角,瀏覽器渲染數據后生成的內容文檔可以看成是一張畫布)。

對於分頁媒體來說,ICB的尺寸為page area(關於ICB在分頁媒體的起始位置,沒有找到相關資料,但這個對於本文來說也不是重點)。

直觀來看,根元素<html />的包含塊ICB,就是“首屏”。

2.5.3. 不同定位元素分別對應的包含塊
static和relative定位元素的包含塊,為其塊級祖先元素(通常是塊級父元素)的content box;
absolute定位元素的包含塊,為最近的非靜態定位祖先元素的padding box,查無非靜態定位祖先元素,那么它的包含塊是ICB(即根元素<html />的包含塊);
fix定位元素的包含塊,為當前viewport(視窗);

在這里要強調的一點,ICB(初始包含塊)是專有名詞,它特指根元素<html />的包含塊。不要將一個元素的初始包含塊,錯誤理解為它的父元素。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM