CSS——CSS 基本視覺格式化:② “行內盒子”格式化

itsOli發表於2019-04-23
本文推薦 PC 端閱讀~

本文版權歸 “公眾號 | 前端一萬小時” 所有,未經授權,請勿轉載!
複製程式碼

CSS——CSS 基本視覺格式化:② “行內盒子”格式化

css_08
複製程式碼

行內盒子.png

行內盒子格式化 問答.png


前言: 作為學習“基本視覺格式化”的第二篇,我們在對上一篇中“塊盒子”整個“格式化”過程中可以得到: 所謂的“格式化”,其實就是確定這個“塊/行內 盒子”的自身長度、高度,以及與其上下左右相鄰“盒子”之間的距離和協調的過程。在確定這個“長度、高度、距離和協調”的過程中會有很多“規則”,那我們學的就是這個“規則”。 接下來的“行內盒子”格式化相對於“塊盒子”格式化的知識點會更細、更分散。不過作為最基本的理論知識,這篇依然很重要。


1 “行內盒子”怎麼來的

當元素的 display 屬性為 inline、inline-block 或 inline-table 時,該元素將成為“行內級元素”。

選擇器 {
    display: inline、inline-block 或 inline-table;
}
複製程式碼

這些元素不會在之前或之後生成“行分隔符”,所以處於正常流中的行內元素會 “水平” 擺放,它們是塊級元素的後代。
顯示時,它不會生成內容塊,但是可以與其他行內級內容一起顯示為多行。
同理,“行內級元素”會生成“行內級盒子”,該盒子同時會參與“行內格式化上下文(inline formatting context)”的建立。

?小總結:
“行內元素”在一個文字內生成“行內盒子”,而不會打斷這行文字(即這種元素可以出現在另一個元素的內容中,而不會破壞其顯示,常見的如:aspanstrongem 等)。

2 “行內盒子”格式化

在正式學習前,有一個觀念我們需要建立:
從某種程度上來講,塊級元素中包含的各“文字行”本身都是“行內元素”(即使它沒有用行內元素的標記包圍起來)。

既然“文字行”可以看作是“行內元素”,那我們就可以把抽象化的“行內元素”、“行內盒子”具象成:給“文字”格式化。然後舉一反三,徹底弄懂與之相關的所有知識。
接下來,我們先學習一些前置基礎知識,然後再細講怎樣“格式化”。

2.1 一些基本概念

2.1.1 匿名文字

<div>生活不像林黛玉<span>不會因為憂鬱</span>而風情萬種</div>
複製程式碼

未包含在行內元素的字串(生活不像林黛玉 而風情萬種)就叫“匿名文字”。

注意,空格也是匿名文字的一部分,因為空格與其他字元一樣都是正常的字元。

2.1.2 非替換元素、替換元素

  • 非替換元素:

如果元素的內容包含在文件中,則稱之為“非替換元素”。
例如:如果一個段落的文字內容都放在該元素的本身之內,這個段落就是一個“非替換元素”。

  • 替換元素:

指用作為其他內容佔位符的一個元素。
例如:
img 元素,它只是指向一個影像檔案,這個影像檔案將插入到文件流中該 img 元素本身所在的位置;
大多數“表單”元素也可以“替換”(如 <input type="radio"> )。

2.1.3 “文字行”基礎概念——內容區、行內框/行內盒子、間距、行框

CSS——CSS 基本視覺格式化:② “行內盒子”格式化
CSS——CSS 基本視覺格式化:② “行內盒子”格式化

1. 內容區
  • 非替換元素中,內容區可以是元素中各字元的 em 框串在一起構成的框(font-size 的值確定了各個 em 框的高度),也可以是由元素中字元字形描述的框。換句話說,內容區的高度就是 font-size 的值。

  • 替換元素中,內容區就是元素的固有高度再加上可能有的 margin、邊框或 padding 。

2. 行間距

行間距是 font-size 與 line-height 的差值,被分成兩半在內容區的上下(上下半間距)。
行間距只應用於非替換元素。

3. 行內框(即行內各個元素對應生成的“行內盒子”)
  • 非替換元素,行內框高度 = line-height ;
  • 替換元素:

① “替換元素”不與文字結合(如 img 元素):行內框高度 = 替換元素的固有高度再加上可能有的 margin、邊框或 padding ;
② “替換元素”文字結合(如 input 中 type=text 、 type=textarea 、 type=button 等與文字結合的表單元素):如果字型行高大於“替換元素的固有高度再加上可能有的 margin、邊框或 padding”,則“行內框”的高度為“行高”。否則就是“替換元素的固有高度再加上可能有的 margin、邊框或 padding”。總之就是“誰大是誰”!

4. 行高

兩行文字“基線”的距離。

5. 行框(即文字整行對應生成的“行內盒子”)

一行有很多“行內盒子——inline box”,“行框”是包含該行中出現的“行內盒子”的最高點和最低點的最小盒子。
換句話說,“行框”的上邊界要位於最高“行內盒子”的上邊界,而“行框”的底邊要放在最低“行內盒子”的下邊界。

6. 基線

不同元素的“基線”位置不同,整個“行框”會有一個“基線”,行內元素的位置是基於兩者“基線”對齊。

2.2 行內盒子格式化

要弄清“行內盒子格式化”,讓我們先充分理解關於“文字”的兩個重要屬性——line-height 和 vertical-align 。

2.2.1 line-height

CSS——CSS 基本視覺格式化:② “行內盒子”格式化

⚠️line-height 隻影響行內元素和其他行內內容,而不影響塊級元素,至少不會直接影響塊級元素。
⚠️line-height有繼承性

2.2.2 vertical-align

作為 line-height 的“斷背”:vertical-align ,這個屬性只能用於“行內元素”和“替換”元素,且不能繼承

行內元素/替換元素 {
    vertical-align: 值;
}
複製程式碼

有以下“值”可以取:

  • baseline
    元素基線與父元素的基線對齊。
    ⚠️對於一些可替換元素,比如 type=textarea , HTML 標準沒有說明它的基線,這意味著對其使用這個關鍵字時,各瀏覽器表現可能不一樣。

  • sub
    元素基線與父元素的下標基線對齊。

  • super
    元素基線與父元素的上標基線對齊。

  • text-top
    元素頂端與父元素字型的頂端對齊。

  • text-bottom
    元素底端與父元素字型的底端對齊。

  • middle
    元素中垂線與父元素的基線加上小寫 x 一半的高度值對齊。

  • <length>
    元素基線超過父元素的基線指定高度(可以取負值)。

  • <percentage>
    <length> ,百分比相對於 line-height ——?這是證明他們倆是“斷背”強有力的證據。

?以下兩個值是相對於整行文字來說的:

  • top
    元素及其後代的頂端與整行的頂端對齊。

  • bottom
    元素及其後代的底端與整行的底端對齊。
    如果元素沒有基線 baseline,則以它的外邊距的下邊緣為基線。

2.3 總結:“行內盒子”格式化步驟概述
CSS——CSS 基本視覺格式化:② “行內盒子”格式化

  • 首先,以下步驟確定文字行中各元素對應的“行內盒子”的高度:
    第一,得到各行內“非替換元素”及不屬於後代行內元素的所有文字的 font-size 值和 line-height 值,再將 line-height 減去 font-size,這就得到了框的“行間距”。這個“行間距”除以 2,將其一半分別應用到 “em 框”的頂部和底部;
    第二,得到各“替換元素”的 height、margin-top、margin-bottom,padding-top、 padding-bottom、border-top-width 和 border-bottom-width 值,把它們加在一起。

  • 其次,對於各內容區,確定它在整行“基線”的上方和下方分別超出多少:
    這個任務並不容易:你必須知道各元素及匿名文字各部分的“基線”的位置, 還要知道該行本身“基線”的位置,然後把它們對齊。另外,對於替換元素,要將其底邊放在整行的“基線”上。

  • 繼而,對於指定了 vertical-align 值的元素,確定其垂直偏移量:
    由此可知該元素的“行內盒子”要向上或向下移動多遠,並改變元素在“基線”上方或下方超出的距離。

  • 最後,既然已經知道了所有“行內盒子”會放在哪裡,再來計算最後的“行內盒子”——行框的高度:
    為此,只需將“基線”與最高“行內框”頂端之間的距離加上“基線”與最低“行內框”底端之間的距離。

2.4 例項講解——弄懂 line-height

2.4.1 ❓問:line-height: 2;line-height: 200%; 有什麼區別?

答:
line-height: 2 和 line-height: 200% 都表示行高是字型大小的 2 倍,但是它們是有區別的。
當它們寫在父容器中時,子元素的字型大小不一樣的時候,區別就體現出來了:

  • line-height: 2; 寫在父容器中,那麼子元素的行高都是自身高度的 2 倍,是相對大小。子元素的字型大小不同,行高也會不同
  • line-height: 200%; 寫在父容器中,那麼瀏覽器會立刻計算出行高的具體值,假如父容器的預設字型大小16px ,那麼計算得到的行高就是 2×16px=32px ,子元素的行高都會繼承這個 32px ,是固定大小。子元素的字型大小不同,行高都是固定某個值。

2.4.2 ❓問:行內元素的“邊框”、“邊界”等“框屬性”是由 font-size 還是 line-height 控制?

答:
對於行內元素來說,上下的 margin padding 不生效,只有左右的 margin padding 生效!
上下 padding 只是撐開了邊框,對高度是沒有影響的。你對他加一些邊框和背景色,他也可以看得到變化,但實質上對高度沒有影響。
所以,行內元素的“邊框”、“邊界”是由 font-size 而不是 line-height 控制。

2.4.3 ❓問:height=line-height 可以用來垂直居中單行文字?

答:是的。
HTML

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>JS Bin</title>
 </head>
 <body>
  <p>Hello Oli的前端一萬小時</p>
 </body>
</html>
複製程式碼

CSS

p {
  width: 300px; 
  border: 1px solid blue;
  height: 50px;
  line-height: 50px;
}
複製程式碼

CSS——CSS 基本視覺格式化:② “行內盒子”格式化

2.5 例項講解——弄懂 inline-block

2.5.1 ❓問:inline-block 有什麼特性?

答:

  • 既呈現 inline 的特性(不佔據一整行,寬度由內容寬度決定);
  • 又呈現 block 特性(可設定寬高,內外邊距)。

2.5.2 ❓問:inline-block 在實際工作中有什麼作用?

答:
如果看到頁面上有一排並列的按鈕,如果不用浮動,就可以用 inline-block 。
HTML

<div class="wrap">
  <span class="box">hello,Oli的前端一萬小時</span>
  <span class="box">hello,Oli的前端一萬小時</span>
 </div>
複製程式碼


CSS

body {
  text-align: center;
}
.box {
  border: 1px solid;
  width: 100px;
  display: inline-block;
}
複製程式碼

CSS——CSS 基本視覺格式化:② “行內盒子”格式化

2.5.3 ❓問:怎麼去除上邊問題中兩個按鈕中間的縫隙問題?

答:
之所以有空隙,是因為 html 文件裡邊兩個 span 之間有很多空白字元,被瀏覽器當做一個,故會有空隙。
解決方式有 2 種:

  • 第一種是在 html 裡邊把這個空格去掉;
<div class="wrap">
  <span class="box">hello,Oli的前端一萬小時</span><span class="box">hello,Oli的前端一萬小時</span>
</div>
複製程式碼
  • 第二種是把包含兩個 span 的 div 字型先設定為 0 (這裡的空白字元就沒有寬度高度,不佔位),然後再在 box 裡邊去設定回去。
body {
   text-align:center;
}
.wrap {
   font-size: 0;
}
.box {
   border:1px solid;
   width: 100px;
   display: inline-block;
   font-size: 14px;
}
複製程式碼

2.5.4 ❓問:一個頁面有一排高度不一樣的產品圖,這時如果我們用 inline-block ,怎樣使他們“頂端對齊”?

答:
HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div class="wrap">
   <span class="box b1">hello,Oli的前端一萬小時</span>
   <span class="box b2">hello,Oli的前端一萬小時</span>
  </div>
</body>
</html>
複製程式碼

CSS

body {
   text-align:center;
}
.wrap {
   font-size: 0;
}
.box {
   border:1px solid;
   width: 100px;
   display: inline-block;
   font-size: 14px;
}
.b1 {
   padding: 40px;
}
.b2 {
   padding: 10px;
}
複製程式碼

以上程式碼會出現以下問題(它會以字的“基線”對齊,而不會以整個框的頂端對齊):

CSS——CSS 基本視覺格式化:② “行內盒子”格式化

如果想對齊(用 vertical-align 屬性):
CSS

body {
  text-align:center;
}
.wrap {
  font-size: 0;
}
.box {
  border: 1px solid;
  width: 100px;
  display: inline-block;
  font-size: 14px;
  vertical-align: top;
}
.b1 {
  padding: 40px;
}
.b2 {
  padding: 10px;
}
複製程式碼

後記: 後續的文章將還會涉及“行內盒子”在例項中的運用,屆時我們還再用程式碼來闡述本篇的基礎理論,眼下不作過多贅述。

我們都要記住一點:理論不懂就實踐,實踐不會就學理論!

加油!

相關文章