css_07 | CSS——CSS 基本視覺格式化:① 「塊盒子」格式化

本文推薦 PC 端閱讀~

本文版權歸 「公衆號 | 前端一萬小時」 全部,未經受權,請勿轉載!
複製代碼

獲取編號.png

css_07
複製代碼

涉及面試題.png

1. 塊級元素和行內元素分別有哪些? 空(void)元素有那些?塊級元素和行內元素有什麼區別?
2. IE 盒模型和 W3C 盒模型有什麼區別?
3. 在什麼場景下會出現外邊距合併?如何合併?如何不讓相鄰元素外邊距合併?給個父子外邊距合併的範例?
4. 關於 .item { width: 100%; },如下說法正確的是:
  ❌ .item 的寬度(包括左右 margin、左右邊框、左右 padding、content)等於它父親的寬度(包括左右 margin、左右邊框、左右 padding、content)。
  ❌ .item 的寬度(包括左右邊框、左右 padding、content)等於它父親的寬度(左右邊框、左右 padding、content)。
  ❌ .item 的寬度(左右 padding、content)等於它父親的寬度(左右 padding、content)。
  ✅ .item 的寬度(content)等於它父親的寬度(content)。
  ❌ 若是設置了 * {box-sizing:border-box},.item 的寬度(包括左右邊框、左右 padding、content)等於它父親的寬度(左右邊框、左右 padding、content)。
複製代碼

前言: 接下來的幾篇系列文章咱們講一個東西:盒子(BOX)。
「盒模型」(box model)做爲 CSS 看待元素的一種方式,CSS 將每一個元素都看做由一個盒子表示。從某方面來講,對於初級、中級學習者的咱們,大可將 CSS 的學習看做是對「盒子」的學習。
爲何這麼說?請看下圖我我的的 CSS 學習流程:css

07-01.png

圖中咱們能夠看到,幾乎全部的內容都是圍繞着「盒子」這個東西在展開。
本篇咱們將闡述最基本的理論知識,將「盒子」的方方面面一步步帶到咱們跟前。html



1 什麼是「盒子」

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

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

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

07-02.png
一個完整的「盒子」


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

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

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

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

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

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

07-03.png
每個元素都是一個「盒子」,「盒子」能夠嵌套「盒子」

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

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

⚠️區別:

  • 「盒子模型」是處理盒子自己的內部屬性——邊距、邊框等;
  • 而「視覺格式化模型」是用來處理這些盒子的擺放。

3 關於「盒子」咱們必定須要知道的——基本視覺格式化

3.1 「盒子」的生成

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

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

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

設置元素的 display 屬性爲 block、list-item 或 table 時,該元素將成爲「塊級元素」。
這些元素在正常流中時,會在其框以前和以後生成「換行」,因此處於
正常流中的塊級元素會「垂直」擺放

選擇器 {
    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)」的建立。

🏆小總結: 相對更詳細的「盒子」細分:

07-04.png

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

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

(對於生成不一樣類型「盒子」在實際項目中的運用,咱們將在後續文章詳細討論。例如:怎樣給「連接」加樣式——生成導航欄、怎樣給「表單」加樣式等。)

3.2 不一樣類型「盒子」在格式化方式上也有所不一樣

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

07-05.png
塊盒子

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。

07-06.png

🚀可詳細分爲如下 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 來垂直居中是不可能的。

07-07.png

垂直格式化的另外一個重要方面是垂直相鄰 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)類型①

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)類型②

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)類型③

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

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

07-08.png

  1. 垂直方向
    (1)類型 ①:負 margin-top
    🔗效果及源碼連接
<!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;
}
複製代碼

07-09.gif
💡把段落1的 margin-top 設爲「負」,它就被向上「拉」了 20 像素,且緊挨它的段落2也相應向上拉了 20 像素。

(2)類型 ②:負 margin-bottom
🔗效果及源碼連接

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;
}
複製代碼

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

(3)類型 ③:正負 margin 合併
「塊盒子」重疊的時候,若是垂直 margin 都爲負值,瀏覽器會取兩個 margin 絕對值的最大值;若是一個正 margin 與一個負 margin 合併,則會從正 margin 減去這個負 margin 的絕對值。
🔗效果及源碼連接

<!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;
}
複製代碼

07-11.gif
💡ul 和 p 重疊的 margin 都爲「負」,則取絕對值較大者(-18px)
07-12.gif
💡當上邊的較大者(-18px)增長到 li 的最大正 margin 上(20px)時,就獲得了 20px - 18px =2px



後記: 這篇咱們學習了「塊盒子」的格式化方式,下一篇咱們接着這篇繼續探討「行內盒子」的格式化方式。在「行內盒子」格式化方式中,咱們會談到不少細小的基礎知識,和本篇的學習方式同樣,讓咱們儘量的用代碼、用圖片來攻克它們。

祝好,qdywxs ♥ you!

相關文章
相關標籤/搜索