【專欄試讀】(07)CSS 基本視覺格式化:① 「塊盒子」格式化 | CSS

2021-03-02 前端一萬小時

前言:接下來的幾篇系列文章我們講一個東西——盒子(BOX)。

「盒模型」(Box Model)作為 CSS 看待元素的一種方式,CSS 將每個元素都看作由一個盒子表示。從某方面來說,對於初級、中級學習者的我們,大可將 CSS 的學習看作是對「盒子」的學習。

本篇我們將闡述最基本的理論知識,將「盒子」的方方面面一步步帶到你的跟前。

1 什麼是「盒子」

「盒子 box」由 CSS 引擎根據文檔中的內容所創建,主要用於文檔元素的格式化、定位和布局等。

盒子與元素並不是一一對應的,有時多個元素會合併生成一個盒子,有時一個元素會生成多個盒子(如匿名盒子)。

一個完整的「盒子」中心有一個內容區(content area)。這個內容區周圍有可選的 padding、邊框和 margin。這些項之所以被認為是可選的,是因為它們的寬度可以設置為 0,實際上就是從「盒子」上去除這些項。

一個完整的「盒子」

2 「視覺格式化模型」概述

CSS 視覺格式化模型(Visual formatting model)是用來處理和在視覺媒體上顯示文檔時使用的計算規則。

通俗地講就是:頁面(文檔樹)可以想像成是由一個個 box 組合而成的,而「視覺格式化模型(Visual formatting model)」是一套規則,將這些 box「布局」成訪問者看到的樣子。

每個盒子的「布局」由以下因素決定(本篇文章和下一篇文章主要講解第 ①、② 點,其屬於「最基本的視覺格式化」,而對於剩下的要點,我們在接下來的系列文章中會挨個討論):

① 盒子的尺寸:精確指定、由約束條件指定或沒有指定;
② 盒子的類型:行內盒子(inline box)、行內級盒子(inline-level box)、原子行內級盒子(atomic inline-level box)、塊盒子(block box);

③ 定位方案(positioning scheme):普通流定位、浮動定位或絕對定位;
④ 文檔樹中的其他元素:即當前盒子的子元素或兄弟元素;
⑤ 視口尺寸與位置;
⑥ 所包含的圖片的尺寸;
⑦ 其他的某些外部因素。

每一個元素都是一個「盒子」,「盒子」可以嵌套「盒子」。

💡如上圖所示,視覺格式化模型會根據盒子的「包含塊」(containing block)——(包含其他盒子的塊稱為「包含塊」)的邊界來渲染盒子。通常,盒子會創建一個包含其後代元素的「包含塊」,但是盒子並不由「包含塊」所限制,當盒子的布局跑到「包含塊」的外面時稱為溢出(overflow)。

上圖中,section 的包含塊是 body,header、article、footer 的包含塊是 section。

❗️區別:

3 關於「盒子」我們一定需要知道的——基本視覺格式化3.1  「盒子」的生成

盒子的生成是 CSS「視覺格式化模型」的一部分,用於從文檔元素生成盒子。

盒子有不同的類型,盒子的類型取決於 CSS 的 display 屬性——元素「角色」的改變。

3.1.1 「塊級元素」和「塊級盒子」

設置元素的 display 屬性為 block、list-itemtable 時,該元素將成為「塊級元素」。

這些元素在正常流中時,會在其框之前和之後生成「換行」,所以處於正常流中的塊級元素會「垂直」擺放

選擇器 {
  display: block、list-item 或 table;
}

💡(「正常流」是指:西方語言文本從左向右、從上向下顯示的方向,這也是我們熟悉的傳統 HTML 文檔的文本布局方向。注意,在非西方語言中,流方向可能不同。)

但,元素是否是「塊級元素」僅是元素本身的屬性,並不直接用于格式化上下文的創建或布局。

一個「塊級元素」會被格式化成一個塊(例如文章的一個段落),且默認按照垂直方向依次排列。

💡一個「塊級元素」都會至少生成一個「塊級盒子」,也有可能生成多個(例如列表項元素)。而「塊級盒子」才會參與「塊格式化上下文(block formatting context)」的創建。

3.1.2 「行內級元素」和「行內盒子」當元素的 display 屬性為 inline、inline-block 或 inline-table 時,該元素將成為「行內級元素」。

選擇器 {
  display: inline、inline-block 或 inline-table;
}

這些元素不會在之前或之後生成「行分隔符」,所以處於正常流中的塊級元素會「水平」擺放,它們是塊級元素的後代。

顯示時,它不會生成內容塊,但是可以與其他行內級內容一起顯示為多行。

💡同理,「行內級元素」會生成「行內級盒子」,該盒子同時會參與「行內格式化上下文(inline formatting context)」的創建。

❗️注意:一定要記得的是,display 之所以得名,是因為它影響的是元素如何「顯示」,而不影響它本質上是何種元素,也就不能亂玩「嵌套關係」!
一個極端的反例就是:你不能讓一個「連結」來包圍一個「段落」。

<a href="http://…" style="display: block;">
<p style="display: inline;">這是一個錯誤的示例</p>
</a>

(對於生成不同類型「盒子」在實際項目中的運用,我們將在後續文章詳細討論。例如:怎樣給「連結」加樣式——生成導航欄、怎樣給「表單」加樣式等。)3.2 不同類型「盒子」在格式化方式上也有所不同

本篇我們主要探討 「塊盒子」格式化,下篇文章討論「行內盒子」格式化。

塊盒子

3.2.1 水平格式化

正常流中,「塊盒子」的水平部分 = 其父元素的 width = 7 個屬性之和——(margin-left ➕ margin-right) ➕ (padding-left ➕ padding-right) ➕ (border-left ➕ border-right) ➕ 內容區自身 width。

在這 7 個屬性中只有 3 個屬性的值可以設置為 auto:width、margin-left、margin-right。其餘的要不必須是確定的值,要不就是默認值 0。

🚀可詳細分為以下 5 種組合:

3 個都不是 auto:按 CSS 的術語來講,這叫「格式化屬性過分受限」,此時總會把 margin-right 強制為 auto 來適應父元素的寬度

2 個不是 auto:是 auto 的將自動調整到適應父級元素的寬度;

margin-left、margin-right 是 auto:它們會自動設置為相等的長度,導致此元素在其父級元素中居中

一個 margin 和 width 是 auto:auto 的 margin 會減為 0,width 自動填充其包含塊;

3 個都是 auto:兩個外邊距減為 0,width 會儘可能的寬(自動充滿)。

❗️注意:由於水平 margin 不會合並,父元素的 padding、邊框、margin 可能會對子元素帶來「偏移」的影響。

3.2.2 垂直格式化

正常流中,「塊盒子」的垂直部分 = 其父元素的 height = 7 個屬性之和——(margin-top ➕ margin-bottom) ➕ (padding-top ➕ padding-bottom) ➕ (border-top ➕ border-bottom) ➕ 內容區自身 height。

同理,在這 7 個屬性中只有 3 個的值可以設置為 auto:height、margin-top、margin-bottom。其餘的要不必須是確定的值,要不就是默認值 0。

❗️不過,margin-top 和 margin-bottom 設置為 auto 也沒有什麼用,因為會被重置為 0。所以,想利用上下 margin 都是 auto 來垂直居中是不可能的。

垂直格式化的另一個重要方面是垂直相鄰 margin 的合併。

這種合併行為只應用於 margin,如果元素有 padding 和邊框,padding 和邊框是不會合併的。當兩個或更多垂直 margin 相遇時,它們將形成唯一一個 margin,這個 margin 的高度等於兩個發生疊加的 margin 的高度中的較大者。

❗️注意:當一個元素包含在另一個元素中時,彼此相鄰的 margin-bottom 和 magin-top 也會發生疊加,取較大者。

3.2.3 負 margin

🤔提問:水平或垂直方向各自 7 大屬性相加要等於父元素的 width 或 height,那 margin 為負值會造成什麼結果?

1. 水平方向

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<div>
  <p class="wide">How are you?</p>
  <p>Fine,thank you,and you?</p>
</div>
</body>
</html>

(1)類型1️⃣

div {
  width: 400px;
  border: 3px solid black;
}

p.wide {
  border: 1px dashed black;
  margin-left: 20px;
  width: auto;
  margin-right: -50px;
  background-color: yellow;
}

(2)類型2️⃣

div {
  width: 400px;
  border: 3px solid black;
}

p.wide {
  border: 1px dashed black;
  margin-left: 20px;
  width: 500px;
  margin-right: auto;
  background-color: yellow;
}

(3)類型3️⃣

div {
  width: 400px;
  border: 3px solid black;
}

p.wide {
  border: 1px dashed black;
  margin-left: -50px;
  width: auto;
  margin-right: 10px;
  background-color: yellow;
}

2. 垂直方向(1)類型 ①:負 margin-top🔗效果及源碼連結
https://jsbin.com/kakiyuqofi/edit?html,css,output

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<div>
  <p class="wide1">How are you?</p>
  <p class="wide2">Fine,thank you,and you?</p>
</div>
</body>
</html>

div {
  width: 400px;
  border: 3px solid black;
}

p.wide1 {
  border: 1px dashed black;
  margin-top: -20px; /* 修改這裡的值來觀察效果 */

  margin-right: 20px;
  margin-bottom: 30px;
  margin-left: 20px;
  width: auto;
  background-color: yellow;
}   

p.wide2 {
  border: 1px dashed black;
  margin-top: ;
  margin-right: 20px;
  margin-bottom: ;
  margin-left: 20px;
  width: auto;
  background-color: grey;
}

💡把段落 1 的 margin-top 設為「負」,它就被向上「拉」了 20 像素,且緊挨它的段落 2 也相應向上拉了 20 像素。
(2)類型 ②:負 margin-bottom🔗效果及源碼連結
https://jsbin.com/quradubano/edit?html,css,output

div {
  width: 400px;
  border: 3px solid black;
}

p.wide1 {
  border: 1px dashed black;
  margin-top: px;
  margin-right: 20px;
  margin-bottom: -50px; /* 修改這裡的值來觀察效果 */

  margin-left: 20px;
  width: auto;
  background-color: yellow;
}   

p.wide2 {
  border: 1px dashed black;
  margin-top: ;
  margin-right: 20px;
  margin-bottom: ;
  margin-left: 20px;
  width: auto;
  background-color: grey;
}

💡把段落 1 的 margin-bottom 設為「負」,段落 2 會根據段落 1 底端的位置放置。

(3)類型 ③:正負 margin 合併

「塊盒子」重疊的時候,如果垂直 margin 都為負值,瀏覽器會取兩個 margin 絕對值的最大值;如果一個正 margin 與一個負 margin 合併,則會從正 margin 減去這個負 margin 的絕對值。

🔗效果及源碼連結
https://jsbin.com/vilatugufi/edit?html,css,output

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<div>
 <ul>
  <li>Fine</li>
  <li>thank you</li>
  <li>and you?</li>
 </ul>
<p>回答 How are you? 的方式!</p>
</div>
</body>
</html>

div {
  width: 400px;
  border: 3px solid black;
}

ul {
  border: 1px dashed black;
  margin-top: px;
  margin-right: 20px;
  margin-bottom: -15px; /* ① 修改這裡的值來觀察效果; */
  margin-left: 20px;
  width: auto;
  background-color: yellow;
}   

li {
  border: 1px dashed black;
  margin-top: ;
  margin-right: 20px;
  margin-bottom: 20px; /* ② 修改這裡的值來觀察效果。 */
  margin-left: 20px;
  width: auto;
  background-color: grey;
}

p {
  border: 1px dashed black;
  margin-top: -18px; /* ① 修改這裡的值來觀察效果。 */
  margin-right: 20px;
  margin-bottom: px;
  margin-left: 20px;
  width: auto;
  background-color: yellow;
}

💡ul 和 p 重疊的 margin 都為「負」,則取絕對值較大者(-18px)。

💡當上邊的較大者(-18px)增加到 li 的最大正 margin 上(20px)時,就得到了 20px - 18px = 2px。

後記:這篇我們學習了「塊盒子」的格式化方式,下一篇我們接著這篇繼續探討「行內盒子」的格式化方式。

在「行內盒子」格式化方式中,我們會談到很多細小的基礎知識,和本篇的學習方式一樣,讓我們儘可能地用代碼、用圖片來攻克它們。

相關焦點

  • 【專欄試讀】(10)讓「盒子」動起來:① 浮動 | CSS
    lt;/div>    <p>      挨到包含塊邊沿或者另一個浮動盒的外邊。lt;/div>    <p>      挨到包含塊邊沿或者另一個浮動盒的外邊。2.5 塊級元素浮動寬度收縮,行內元素浮動以塊級特性去呈現🔗源碼及效果展示https://jsbin.com/sotonifaqu/edit?html,css,outputHTML<!
  • DIV+CSS學習筆記總結篇:盒子模型和塊元素、行元素與溢出
    :盒子模型就是一個有高度和寬度的矩形區域所有html標籤都是盒子模型div標籤自定義盒子模型所有的標籤都是盒子模型class和id的主要差別是:class用於元素組(類似的元素,或者可以理解為某一類元素
  • JavaScript/HTML格式化
    JavaScript/HTML格式化 - 站長工具 可以對JS,HTML進行格式化排版,整齊的進行顯示。...JS/HTML格式化工具簡單易用的JS/HTML格式化工具請在下框輸入您要轉換的內容:懶人工具箱 全部 01. HTML/JS轉換工具 02.
  • 網頁設計:關於CSS框架網頁的設計!
    2、css框架的開發順序   a) 格式化 reset.css   格式化css的真正好處是能夠快速啟動工作,你可以在新的HTML文件裡引入框架,不用再處理重置padding 和 margins,實現統一的排版、瀏覽器下的相同表現。
  • CSS中內聯元素與塊級元素
    塊元素(block element)一般是其他元素的容器元素,塊元素一般都從新行開始,它可以容納內聯元素和其他塊元素,常見塊元素是段落標籤』P」。「form」這個塊元素比較特殊,它只能用來容納其他塊元素。如果沒有css的作用,塊元素會順序以每次另起一行的方式一直往下排。而有了css以後,我們可以改變這種html的默認布局模式,把塊元素擺放到你想要 的位置上去。
  • CSS核心基礎之CSS基礎知識介紹
    樣式表是由一系列樣式選擇器和CSS屬性組成,它支持字體屬性、顏色和背景屬性、文本屬性、邊框屬性、列表屬性以及精確定位網頁元素屬性等,增強了網頁的格式化功能。CSS樣式實際上可以看成是屬性的集合。2. CSS的特點除了可擴展HTML的樣式設定外,CSS的特點主要包含如下幾點:1.減少圖形文件的使用。2.集中管理樣式信息。3.共享樣式設定。4.將樣式分類使用。3.
  • 104道 CSS 面試題,助你查漏補缺(上)
    27.對 BFC 規範(塊級格式化上下文:block formatting context)的理解?IFC指的是行級格式化上下文,它有這樣的一些布局規則:(1)行級上下文內部的盒子會在水平方向,一個接一個地放置。(2)當一行不夠的時候會自動切換到下一行。(3)行級上下文的高度由內部最高的內聯盒子的高度決定。
  • CSS的盒子模型和浮動,都在這了
    點關注,不迷路,每天分享大量前端知識css中的盒子模型 css處理網頁時,他認為每個元素都包含在一個不可見的矩形盒子 盒子是由 內容區,內邊距(padding),邊框,外邊距(margin)組成在瀏覽器中,其默認樣式中存在一些body等元素存在的默認樣式,比如一些外邊距
  • 前端開發必會的HTML/CSS硬知識
    2 塊元素和行元素2.1 請說出3個H5新增的塊元素,並介紹他們的應用場景aside:表示article元素內容之外,與article元素內容相關的輔助信息figure:代表一個塊級圖像,包含說明。佔用高:margin*2+padding*2+border*2+height= 20*2+10*2+10*2+50 = 1303. 盒子實際寬度:padding*2+border*2+width= 10*2+10*2+200 = 2404. 盒子實際高度padding*2+border*2+height= 10*2+10*2+50 = 90
  • 前端進階:css必知的幾個底層知識和技巧
    在介紹完問題學習法之後,進入我們今天的主題,接下來我會介紹css的一些底層的知識的現象,藉此來讓大家對css有更深入的理解。:內聯標籤或者純文本行框盒子:由內聯盒子組成的一行,每一行就是一個行框盒子包含盒子:由行框盒子組成的盒子 幽靈空白節點:在HTML5文檔聲明中,內聯元素的解析和渲染表現就像每個行框盒子的前面有一個空白節點一樣。
  • CSS Display屬性的雙值寫法
    display屬性用來控制一個元素及其子元素的格式化上下文,你應該在剛剛學習CSS的時候就知道,有些元素是塊級元素,有些則是行內元素。有了display屬性,你就可以切換元素不同的狀態。比如說,通常一個h1元素是一個塊級元素,但是通過切換,它就能以內聯元素展現。這幾年,我們也知道了Grid 布局和彈性盒布局。
  • 前端基礎篇之CSS世界
    另外本文會隨著作者對css的更深入理解而逐步更新,希望到最後能夠文如標題展現出真正的css世界。小剛老師基本概念這些基本概念有些可能不易理解但卻都很重要,如果看完還是很不理解的話需要自己谷歌或百度,網上關於這些概念的文章不少。流「流」又叫文檔流,是css的一種基本定位和布局機制。
  • 關於CSS不得不知的9條面試經驗
    二、內容不同1、CSS3:主要包括盒子模型、列表模塊、超連結方式、語言模塊、背景和邊框、文字特效、多欄布局等模塊。2、CSS:不僅可以靜態地修飾網頁,還可以配合各種腳本語言動態地對網頁各元素進行格式化。
  • CSS學習筆記總結
    層疊特性基本選擇器出現衝突時優先級問題id選擇器>類別選擇器>標記選擇器 與順序無關這裡如果添加上內行式,則以內行式為準在css中一般id選擇器的屬性值儘量在全文中唯一class沒有這個限制
  • 【面試題】CSS知識點整理(附答案)
    css引入偽類和偽元素概念是為了格式化文檔樹以外的信息。偽類和偽元素是用來修飾不在文檔樹中的部分。偽類偽類 用於當元素處於某個狀態時,為其添加對應的樣式,這個狀態是根據用戶行為而動態變化的。清除浮動常用的四種方式:額外標籤法:在有浮動的父級元素的末尾插入了一個沒有內容的塊級元素div 並添加樣式clear:both。
  • CSS教程之超級快速入門教程
    css是一種用來表現HTML(標準通用標記語言的一個應用)或XML(標準通用標記語言的一個子集)等文件樣式的計算機語言。CSS不僅可以靜態地修飾網頁,還可以配合各種腳本語言動態地對網頁各元素進行格式化。
  • 前端進階: css必知的幾個底層知識和技巧
    在介紹完問題學習法之後,進入我們今天的主題,接下來我會介紹css的一些底層的知識和比較詭異的現象,藉此來讓大家對css有更深入的理解。一.css尺寸1.首選最小寬度–實現複雜圖形效果在css中,圖片和文字的權重遠大於布局,因此當width:0時表現出來的寬度就是「首選最小寬度」。中文的最小寬度為每個漢字的寬度,西方文字取決於連續的英文字符單元。
  • CSS基礎:基礎和語法
    引入CSS樣式如何插入樣式表,當讀到一個樣式表時,瀏覽器會根據它來格式化 HTML 文檔。插入樣式表的方法有三種:外部樣式表、內部樣式表和內聯樣式。標籤在(文檔的)頭部:<head><link rel="stylesheet" type="text/css" href="site.css" /></head>2.內部樣式表當單個文檔需要特殊的樣式時,就應該使用內部樣式表。
  • 面試整理(三)CSS部分
    如何創建塊級格式化上下⽂(block formatting context),BFC有什麼用?⾏內元素 float:left 後是否變為塊級元素?⾏內元素設置成浮動之後變得更加像是 inline-block 既:⾏內塊級元素,設置成這個屬性的元素會同時擁有⾏內和塊級的特性,最明顯的不同是它的默認寬度不是 100% ,這時候給⾏內元素設置 padding-top 和 padding-bottom 或者 width 、 height 都是有效果的
  • 104道CSS面試題,助你查漏補缺
    css 實現上下固定中間自適應布局?css 兩欄布局的實現?css 三欄布局的實現?實現一個寬高自適應的正方形實現一個三角形一個自適應矩形,水平垂直居中,且寬高比為 2:11.介紹一下標準的 CSS 的盒子模型?低版本 IE 的盒子模型有什麼不同的?