前言
我們經常使用CSS,但是卻不怎么了解CSS,本文主要對vertical-align、BFC、position中開發過程不怎么注意的特性進行簡要總結,從本文中,你將了解到以下內容:
vertical-align為何時靈時不靈BFC是什么?有何作用- 絕對定位的奇淫技巧
CSS特性
vertical-align為什么時靈時不靈
生效條件
只能應用在display為inline、inline-block、inline-table、table-cell上。
有個高頻面試題,“如何使一個不定寬高div垂直水平居中?”,有的萌新竟然回答用vertical-align: middle。這個回答是減分的,至少在某種程度上給人一種感覺CSS基礎比較薄弱。
內聯元素垂直居中對齊
開發中會遇到用字幕x代替關閉icon,用...顯示溢出或者加載中。但是會發現字母x、省略號並沒有與文本垂直方向居中對齊,這是因為文本默認是基線對齊,x、省略號默認底部在基線處。如下圖所示:

如下,為文本對齊demo:
<div class="container">
<span>你好,世界</span>
<span class="more">...</span>
</div>
實際顯示效果如下:

如果要實現垂直居中,利用vertical-align,搭配line-height即可,vertical-align不僅可以設置middle/top/bottom/baseline...關鍵字,也可以設置常用的度量單位,正負值均可,使用比較靈活。為什么要給.more設置line-height屬性呢?其實是因為line-height屬性可以繼承,如果不縮小.more的行高,就會撐大父元素的尺寸。
<style>
.container{
font-size: 64px;
line-height: 64px;
}
.more{
line-height: 16px;
vertical-align: 16px;
}
</style>
BFC究竟有什么作用
什么是BFC
BFC全稱block formatting context,即“塊狀格式化上下文”,與外界元素相對獨立的一片區域,具有以下特性:
- 計算
BFC高度時,浮動元素也參與計算 - 屬於同一
BFC容器的元素垂直方向的margin會合並 BFC容器是獨立容器,不會影響外部元素的布局
利用BFC的特性,我們可以實現以下功能:
- 清除浮動
- 防止垂直方向
margin合並 - 實現多欄彈性布局
BFC的生效條件
以下CSS屬性會觸發元素生成BFC結界:
- 根元素(
<html>) - 浮動元素(元素的
float不是none) - 絕對定位元素(元素的
position為absolute或fixed) - 行內塊元素(元素的
display為inline-block) - 表格單元格(元素的
display為table-cell,HTML表格單元格默認為該值) - 表格標題(元素的
display為table-caption,HTML表格標題默認為該值) - 匿名表格單元格元素(元素的
display為table、table-row、table-row-group、table-header-group、table-footer-group(分別- 是HTML table、row、tbody、thead、tfoot的默認屬性)或inline-table) overflow計算值(Computed)不為visible的塊元素display值為flow-root的元素contain值為layout、content或paint的元素- 彈性元素(
display為flex或inline-flex元素的直接子元素) - 網格元素(
display為grid或inline-grid元素的直接子元素) - 多列容器(元素的
column-count或column-width不為auto,包括column-count為 1) column-span為all的元素始終會創建一個新的BFc
BFC使用案例
- 清除浮動
<style>
.container{
/* overflow: hidden; */
/* position: absolute; */
/* float: left; */
}
.left{
float: left;
width: 200px;
height: 200px;
}
</style>
<div class="container">
<div class="left"></div>
</div>
以上代碼,container容器高度為0,因為子元素left浮動。我們只需要把container容器轉成BFC容器,即可清楚浮動,注釋的幾種方法都可以。
- 防止垂直方向
margin合並
<style>
.blue, .red-inner {
height: 50px;
margin: 10px 0;
}
.blue {
background: blue;
}
.red-outer {
overflow: hidden;
background: red;
}
</style>
<div class="blue"></div>
<div class="red-outer">
<div class="red-inner">red inner</div>
</div>
- 自適應布局
左側固定,右側自適應。
<style>
.left{
height: 200px;
width: 200px;
float: left;
background-color: burlywood;
}
.right{
height: 200px;
margin-left: 200px;
background-color: cadetblue;
}
</style>
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
絕對定位還能玩出什么花樣
簡介
絕對定位使用場景非常多。絕對定位元素脫離文檔流,相對於最近的非 static 祖先元素定位,可以利用left/right/top/bottom定位元素位置。我們通常都是設置垂直方向與水平方向的的位置,如果四個方向都不設置或者四個方向都設置會出現什么彩蛋呢?下文會給出揭曉。
left/top/right/bottom都有值的定位
- 當對立位置(
left與right,top與bottom)都設置值且元素沒用固定寬高
此時元素的寬高是根據元素位置決定的,張鑫旭大佬在《CSS世界》中定義為格式化寬高,如下代碼,最終box-item的寬高計算為:width = 200 - 50 -50 = 100px;width = 200 - 50 -50 = 100px;
<style>
.box{
position: relative;
width: 200px;
height: 200px;
margin: 50px;
background-color: bisque;
}
.box-item{
position: absolute;
left: 50px;
right: 50px;
top: 50px;
bottom: 50px;
background-color: coral;
}
</style>
<div class="box">
<div class="box-item"></div>
</div>
這種行為特性對於我們做自適應布局非常有用,而且兼容性非常好,比如我們要做左側固定寬度,右側自適應,除了以上BFC的寫法,我們還可以采用以下方法:
<style>
.container{
position: absolute;
top: 100px;
bottom: 100px;
left: 0;
right: 0;
}
.left{
position: absolute;
top: 0;
bottom: 0;
width: 200px;
background-color: burlywood;
}
.right{
position: absolute;
left: 200px;
right: 0;
top: 0;
bottom: 0;
background-color: cadetblue;
}
</style>
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
- 當對立位置都設置了值且元素設置了固定寬高
這個時候你會發現,元素的寬高時以width/height為准,上述說的格式化寬度、高度並沒有生效。這是因為在高度計算過程中,元素的內部尺寸優先級大於外部尺寸,width/height影響的是元素內部尺寸,絕對定位影響的是外部尺寸,當元素絕對定位四個方向都設置值,此時外部尺寸會被內部尺寸覆蓋,導致實際元素寬度是width/height的值。
我們經常用margin: 0 auto;實現元素水平居中,但是不定寬高元素垂直水平居中就有些麻煩。但是有個神奇的現象,絕對定位配合margin: auto;,可以實現元素垂直水平居中,如下所示:
<style>
.box{
position: relative;
width: 200px;
height: 200px;
margin: 50px;
background-color: bisque;
}
.box-item{
position: absolute;
margin: auto;
width: 50px;
height: 50px;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: coral;
}
</style>
<div class="box">
<div class="box-item"></div>
</div>
出現這種現象是因為margin:auto本質上是平分元素剩余可用空間,塊級元素一般是水平方向自動充滿,垂直方向順序排列。平常我們用margin: 0 auto;之所以能夠使塊級元素水平居中,是因為水平方向元素存在剩余可用空間,而auto平分剩余可用空間,因此就產生居中效果。而垂直方向不存在剩余可用空間,因此無法垂直居中。
上述demo,box-item之所以能夠垂直居中,得益於top/bottom設置了值,使元素產生高度100%的外部尺寸,而width/height固定元素的內部尺寸,使得 外部尺寸高度-內部尺寸高度=元素剩余可用空間高度,而auto等分剩余可用空間,可以使元素達到垂直居中效果。可以嘗試調整四個方向的值,看看box-item位置是怎么移動的。
無依賴的絕對定位
當絕對定位沒有設置四周定位尺寸時,會發生神奇的一幕,當前元素沒有相對於最近的非 static 祖先元素定位,而是在當前位置不變,並且當前元素脫離文檔流,不占據頁面空間。這個特性某些情況下非常有用,比如給box-card加一個圖標,借助無依賴定位 + padding/margin即可。寫法比較簡潔,建議嘗試一下。
小結
比起其他的開發語言,想要深入了解CSS,並不是一件容易事,大多數人都是停留在用的基礎上,知道這個屬性/方法,至於為什么會這樣了解較少。張鑫旭大佬CSS高度讓人嘆為觀止,繼續加油吧!!!
參考資料
- 《
CSS世界》 - BFC
