本文推薦 PC 端閱讀~
本文版權歸 “公眾號 | 前端一萬小時” 所有,未經授權,請勿轉載!
複製程式碼
css_08
複製程式碼
前言: 作為學習“基本視覺格式化”的第二篇,我們在對上一篇中“塊盒子”整個“格式化”過程中可以得到: 所謂的“格式化”,其實就是確定這個“塊/行內 盒子”的自身長度、高度,以及與其上下左右相鄰“盒子”之間的距離和協調的過程。在確定這個“長度、高度、距離和協調”的過程中會有很多“規則”,那我們學的就是這個“規則”。 接下來的“行內盒子”格式化相對於“塊盒子”格式化的知識點會更細、更分散。不過作為最基本的理論知識,這篇依然很重要。
1 “行內盒子”怎麼來的
當元素的 display 屬性為 inline、inline-block 或 inline-table 時,該元素將成為“行內級元素”。
選擇器 {
display: inline、inline-block 或 inline-table;
}
複製程式碼
這些元素不會在之前或之後生成“行分隔符”,所以處於正常流中的行內元素會 “水平” 擺放,它們是塊級元素的後代。
顯示時,它不會生成內容塊,但是可以與其他行內級內容一起顯示為多行。
同理,“行內級元素”會生成“行內級盒子”,該盒子同時會參與“行內格式化上下文(inline formatting context)”的建立。
?小總結:
“行內元素”在一個文字內生成“行內盒子”,而不會打斷這行文字(即這種元素可以出現在另一個元素的內容中,而不會破壞其顯示,常見的如:a
、 span
、 strong
、 em
等)。
2 “行內盒子”格式化
在正式學習前,有一個觀念我們需要建立:
從某種程度上來講,塊級元素中包含的各“文字行”本身都是“行內元素”(即使它沒有用行內元素的標記包圍起來)。
既然“文字行”可以看作是“行內元素”,那我們就可以把抽象化的“行內元素”、“行內盒子”具象成:給“文字”格式化。然後舉一反三,徹底弄懂與之相關的所有知識。
接下來,我們先學習一些前置基礎知識,然後再細講怎樣“格式化”。
2.1 一些基本概念
2.1.1 匿名文字
<div>生活不像林黛玉<span>不會因為憂鬱</span>而風情萬種</div>
複製程式碼
未包含在行內元素的字串(生活不像林黛玉 而風情萬種)就叫“匿名文字”。
注意,空格也是匿名文字的一部分,因為空格與其他字元一樣都是正常的字元。
2.1.2 非替換元素、替換元素
- 非替換元素:
如果元素的內容包含在文件中,則稱之為“非替換元素”。
例如:如果一個段落的文字內容都放在該元素的本身之內,這個段落就是一個“非替換元素”。
- 替換元素:
指用作為其他內容佔位符的一個元素。
例如:
img 元素,它只是指向一個影像檔案,這個影像檔案將插入到文件流中該 img 元素本身所在的位置;
大多數“表單”元素也可以“替換”(如 <input type="radio">
)。
2.1.3 “文字行”基礎概念——內容區、行內框/行內盒子、間距、行框
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
⚠️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 總結:“行內盒子”格式化步驟概述
-
首先,以下步驟確定文字行中各元素對應的“行內盒子”的高度:
第一,得到各行內“非替換元素”及不屬於後代行內元素的所有文字的 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;
}
複製程式碼
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;
}
複製程式碼
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;
}
複製程式碼
以上程式碼會出現以下問題(它會以字的“基線”對齊,而不會以整個框的頂端對齊):
如果想對齊(用 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;
}
複製程式碼
後記: 後續的文章將還會涉及“行內盒子”在例項中的運用,屆時我們還再用程式碼來闡述本篇的基礎理論,眼下不作過多贅述。
我們都要記住一點:理論不懂就實踐,實踐不會就學理論!
加油!