CSS 垂直置中技巧
這篇教學會介紹多種 CSS「垂直置中」的實用技巧,運用行高、定位、對齊以及 Flex 彈性排版、Grid 網格排版等方式,分別將行內容器 ( 單行文字、多行文字等 ) 和區塊容器 ( h1~h6、div 等 ) 套用垂直置中的效果,最後還會示範同時垂直水平置中的做法。
延伸閱讀:CSS 水平置中技巧
快速導覽:
垂直置中技巧列表
正規作法 ( 推薦 )
所謂的正規作法,表示單純依靠 CSS 所提供的垂直置中功能以及基本原理,就能實現垂直置中效果,這些做法較為彈性且符合大多數情境,是較為推薦的方法。
垂直置中技巧 單行 多行 作用元素 line-height O X inline-*
vertical-align O O inline-*
、table-*
,需搭配line-height
align-self ( grid ) O X 網格項目 align-items ( flex、grid ) O X 彈性容器、網格容器 align-content ( flex、grid ) X O 彈性容器、網格容器,需搭配 align-items
非正規作法
非正規的做法表示透過兩三種樣式屬性互相搭配,使得元素的位置看起來像是垂直置中,由於必須使用多種定位和排版方式,且有時還得搭配手動設定數值,使用後較不彈性且容易出錯,建議在上述正規作法都無法實現時,再考慮透過這些方式處理垂直置中。
垂直置中技巧 單行 多行 作用元素 padding + transform O O inline-*
,需搭配手動計算或line-height
top + transform O O inline-*
,需搭配手動計算或line-height
行高 line-height
行高 line-height
是常用的垂直置中技巧,但僅適用於版面為「單行文字」的排版,嚴格來說 line-height
不能算是垂直置中的樣式屬性,只是透過行高的方式,讓單一行裡的文字保持同等的高度尺寸,當「行高與父元素高度相同時」,就會產生垂直置中的效果,在不同顯示類型的容器中使用行高進行垂直置中,會有下列的差異:
- 詳細參考:文字行高、文字縮排
- 不同顯示類型元素差異:
- 行內容器:會採用同層級元素的「最大行高」。
- 區塊容器:未設定高度的元素,高度為所內容預設或手動設定的行高。
下方範例會使用三組 div 呈現 line-height
垂直置中的不同,三組 div 中不同元素的行高都不同,但如果都是行內容器,會採用同層級的最大行高,如果是區塊容器,區塊容器的高度就會隨行高發生變化。
<!-- HTML 程式碼 -->
內容為行內容器 ( 採用最大行高 )
<div class="a">Apple <span>banana</span> <em>oxxo</em> <strong>papaya</strong></div>
內容為區塊容器 ( 行高相同 )
<div class="b"><div>Apple</div> <div>banana</div> <div>oxxo</div> <span>papaya ( 行內容器 )</span></div>
內容為區塊容器 ( 行高不同 )
<div class="c"><div>Apple</div> <div>banana</div> <div>oxxo</div> <span>papaya ( 行內容器 )</span></div>
<!-- CSS 程式碼 -->
<style>
div[class] {
border: 1px solid #000;
height: 100px;
margin: 5px 0 20px 0;
}
/* 行內容器就算行高不同,仍然會採用同層級最大行高,所有內容垂直置中 */
.a {line-height: 100px;}
.a span {line-height: 50px;}
.a em {line-height: 5px;} /* 行內容器就算行高很小,仍然會採用同層級最大行高 */
/* 區塊容器如果未設定高度,則高度隨行高變化,除非高度相同,不然都是對齊上緣 */
.b, .c {line-height: 100px;}
.b div, .c div {
float: left; /* 變成浮動元素,讓區塊容器可以水平排列 */
margin-right: 5px;
background: #faa; /* 使用背景色凸顯實際尺寸 */
}
.c div:nth-child(2){line-height: 50px;}
.c div:nth-child(3){line-height: 5px;}
.b span, .c span {line-height: 10px;} /* 行內容器就算行高很小,仍然會採用同層級最大行高 */
</style>
垂直對齊 vertical-align
垂直對齊 vertical-align
是只有「行內容器」和「表格容器」才有作用的垂直對齊樣式屬性,只要是這兩種顯示類型的元素,就可以透過垂直對齊中線的方式,實現垂直置中效果,使用時需要注意下列事項:
- 詳細參考:vertical-align 垂直對齊
vertical-align
只有「行內容器」和「表格容器」才有作用。- 如果父元素高度較大,需額外將父元素的
line-height
的數值設定與高度相同。- 由於不同字型和字母大小寫的中線有所不同,垂直對齊之後可能無法真正垂直置中。
- 多行文字與單行文字垂直置中時,需要將多行文字包覆在
inline-block
容器中,避免行內容器的換行連動。
下方範例會使用 vertical-align: middle
讓 div
裡的所有元素垂直對齊中線,如果是區塊容器,只需要透過 display:inline-block
的轉換顯示類型,就能產生垂直置中的效果。
<!-- HTML 程式碼 -->
不同尺寸的文字垂直置中
<div>Apple <span>Banana</span> <em>oxxo</em> <strong>Papaya</strong></div>
div 轉換顯示類型後與文字垂直置中
<div><div>Apple</div> <div>Banana</div> <div>oxxo</div> <strong>Papaya</strong></div>
div 轉換顯示類型後的多行、單行文字垂直置中
<div><div>Apple</div> <div>Banana<br>Coconut</div> <div>多行文字<br>hello</br>oxxo</div> <strong>Papaya</strong></div>
div 轉換類型與圖片、文字垂直置中
<div><div>Apple</div> <img src="https://steam.oxxostudio.tw/download/css/function-filter-demo.png"> <strong>Papaya</strong></div>
<!-- CSS 程式碼 -->
<style>
body > div {
margin: 5px 0 20px 0;
width: 400px;
}
div {border: 1px solid #000;}
div * {vertical-align: middle;} /* div 裡所有元素都垂直對齊中線 */
div div {display: inline-block;} /* div 裡的 div 轉換成 inline-block */
span {font-size: 30px;} /* 文字尺寸變大 */
strong {font-size: 50px;} /* 文字尺寸變大 */
img {width: 150px;}
</style>
如果子元素是多個高度不同的區塊容器,也可以搭配 line-height
的做法,將父元素的「高度和行高設為相同數值」,由於行高具有繼承特性,所有子元素就會根據最大的行高進行垂直對齊,進而實現垂直置中的效果。
<!-- HTML 程式碼 -->
<div><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
<!-- CSS 程式碼 -->
<style>
div {
margin: 5px 0 25px 0;
border: 1px solid #000;
width: 400px;
height: 100px; /* 父元素的行高與高度相同 */
line-height: 100px; /* 父元素的行高與高度相同 */
}
div * {
display: inline-block;
border: 1px solid #000;
vertical-align: middle; /* 垂直對齊中線 */
line-height: 1.2; /* 子元素的行高使用預設值 1.2,避免繼承後影響效果 */
}
</style>
flex 排版 align-items、align-content
當元素顯示類型為 flex
,子元素都會轉換為彈性項目,這時可以透過彈性排版的方式,透過 align-items
和 align-content
樣式屬性,進行單行元素或多行元素的垂直對齊,雖然內容元素都會變成彈性項目,但卻是相當實用的垂直置中技巧。
- 詳細參考:Flex 元素的對齊方式
- 這種方式會將子元素轉換成彈性項目,因此子元素都需要用標籤包覆。
- 使用
align-items
只能進行「單行」垂直置中。- 使用
align-content
搭配align-content
可進行「多行」垂直置中。
下方範例會使用 flex 排版的 align-items
和 align-content
進行「單行」與「多行」元素的垂直置中。
<!-- HTML 程式碼 -->
單行 flex 項目
<div><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
多行 flex 項目 ( 縮小父元素寬度,搭配 flex-wrap: wrap; )
<div class="a"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
<!-- CSS 程式碼 -->
<style>
div {
display: flex; /* 建立 flex 容器,子元素全部變成彈性項目 */
height: 150px;
width: 300px;
border: 1px solid #000;
margin: 5px 0 20px;
align-items: center; /* 子元素單行垂直置中 */
}
.a {
width: 200px;
flex-wrap: wrap; /* 內容寬度超過父元素寬度時換行 */
align-content: center; /* 子元素多行垂直置中 */
}
div * {
margin: 0; /* 避免子元素自帶的 margin 影響 */
padding: 0;
border: 1px solid #000;
}
</style>
grid 排版 align-self、align-items、align-content
當元素顯示類型為 grid
,子元素都會轉換為網格項目,這時可以透過網格排版的方式,透過 align-self
、align-items
和 align-content
樣式屬性,進行單行元素或多行元素的垂直對齊。
- 詳細參考:Grid 網格項目對齊、順序與重疊
- 這種方式會將子元素轉換成網格項目,因此子元素都需要用標籤包覆。
- 使用
align-self
作用「網格項目」,只能進行「單行」垂直置中。- 使用
align-items
作用「網格容器」,只能進行「單行」垂直置中 ( 效果與align-self
相同 )。- 使用
align-content
作用「網格容器」,進行「多行」垂直置中。
下方範例會使用 grid 排版的 align-self
、align-items
和 align-content
樣式屬性,進行「單行」與「多行」元素的垂直置中。
<!-- HTML 程式碼 -->
單行 grid 項目 ( 作用於網格項目 )
<div class="a"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
單行 grid 項目 ( 作用於網格容器 )
<div class="b"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
多行 grid 項目 ( 作用於網格容器 )
<div class="c"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
<!-- CSS 程式碼 -->
<style>
div {
display: grid; /* 轉換為網格容器 */
height: 120px;
width: 300px;
border: 1px solid #000;
margin: 5px 0 20px;
grid-template-columns: repeat(4, 1fr); /* 一列四欄,每欄寬度平均分配 1fr */
}
div * {
margin: 0;
padding: 0;
height: 40px;
border: 1px solid #000;
background: #f99;
}
.a * {align-self: center;} /* 網格項目單行垂直置中 */
.b {align-items : center;} /* 網格容器裡的項目單行垂直置中 */
.c {
grid-template-columns: repeat(2, 1fr); /* 一列二欄,每欄寬度平均分配 1fr */
grid-template-rows: repeat(2, 40px); /* 一欄兩列,每列高度 50% */
align-items : center; /* 網格容器裡的項目單行垂直置中 */
align-content : center; /* 網格容器裡的項目多行垂直置中 */
}
</style>
padding 搭配 transform、translate
padding
樣式屬性可以設定父元素的「內邊距」,只要設定父元素「上方」的內邊距,再透過 transform
樣式屬性的 translate()
函式或 translate
樣式屬性將元素往上移動,就能實現垂直置中效果,這種使用作法並非正規作法,有時需要額外設定不少樣式屬性,且設定時較不彈性,可參考下列注意事項:
- 詳細參考:內邊距 padding、translate() 平移函式、translate 平移
padding
的百分比數值會乘以「父元素的寬度」,進行垂直置中時必須設定為「絕對長度」單位,並搭配box-sizing: border-box
避免影響元素尺寸。translate
或translate()
的百分比數值會根據「方向」乘以「元素本身的寬度或高度」。- 如果子元素字體大小不同,需額外搭配
line-height
和vertical-align
。
下方範例會使用四種不同字體尺寸的子元素,透過 padding
搭配 transform
、translate
進行垂直置中。
<!-- HTML 程式碼 -->
translate: 0 -50%;
<div class="a"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
transform: translate(0, -50%);
<div class="b"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
transform: translate(0, -50%); 搭配垂直對齊與行高
<div class="c"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
<!-- CSS 程式碼 -->
<style>
div {
height: 100px;
width: 360px;
border: 1px solid #000;
margin: 5px 0 20px;
padding-top: 50px; /* padding-top 為高度的一半 */
box-sizing: border-box; /* 設定為 border-box 避免影響尺寸 */
}
div * {
margin: 0;
padding: 0;
border: 1px solid #000;
background: #f99;
display: inline-block; /* 內容元素改成 inline-block */
}
.a * {translate: 0 -50%;} /* 往 Y 方向移動 -50% 元素本身高度 */
.b * {transform: translate(0, -50%);} /* 往 Y 方向移動 -50% 元素本身高度 */
.c * {
transform: translate(0, -50%); /* 往 Y 方向移動 -50% 元素本身高度 */
line-height: 50px; /* 設定行高 */
vertical-align: middle; /* 垂直置中對齊 */
}
</style>
使用這種做法如果遇到「多行」情境,在子元素尺寸不同或字體大小不同的情況下,往上平移的數值就需要與 line-height
相同,才不會發生位移後與行高不同而無法垂直置中,下方範例會展示這種差異。
<!-- HTML 程式碼 -->
translate: 0 -50%; ( 沒有垂直置中 )
<div class="a"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
translate: 0 -70px; 搭配行高與垂直對齊
<div class="b"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
<!-- CSS 程式碼 -->
<style>
div {
height: 240px;
width: 200px;
border: 1px solid #000;
margin: 5px 0 20px;
padding-top: 120px;
box-sizing: border-box;
}
div * {
margin: 0;
padding: 0;
border: 1px solid #000;
background: #f99;
display: inline-block;
}
.a * {translate: 0 -50%;}
.b * {
line-height: 70px; /* 設定行高 */
translate: 0 -70px; /* 往上平移數值與行高相同 */
vertical-align: middle;
}
</style>
top 搭配 transform、translate
top
樣式屬性可以設定元素與參考容器上緣之間的距離,設定後再透過 transform
樣式屬性的 translate()
函式或 translate
樣式屬性將元素往上移動,就能實現垂直置中效果,這種使用作法並非正規作法,有時需要額外設定不少樣式屬性,且設定時較不彈性,可參考下列注意事項:
- 詳細參考:位置距離:top、bottom、left、right、translate() 平移函式、translate 平移
top
樣式屬性適用於「定位樣式非 static」的元素,必須將元素設定position:relative
才能套用top
樣式屬性。translate
或translate()
的百分比數值會根據「方向」乘以「元素本身的寬度或高度」。- 如果子元素字體大小不同,需額外搭配
line-height
和vertical-align
。
下方範例會使用四種不同字體尺寸的子元素,透過 padding
搭配 transform
、translate
進行垂直置中。
<!-- HTML 程式碼 -->
top: 50%; 搭配 translate: 0 -50%;
<div class="a"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
top: 50%; 搭配 transform: translate(0, -50%);
<div class="b"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
top: 50%; 搭配 transform: translate(0, -50%); ( 行高與垂直對齊 )
<div class="c"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
<!-- CSS 程式碼 -->
<style>
div {
height: 120px;
width: 360px;
border: 1px solid #000;
margin: 5px 0 20px;
}
div * {
margin: 0;
padding: 0;
border: 1px solid #000;
background: #f99;
display: inline-block;
position: relative; /* 子元素設定為 relative */
top: 50%; /* 與父元素上緣距離為父元素高度的 50% */
}
.a * {translate: 0 -50%;} /* 往 Y 方向移動 -50% 元素本身高度 */
.b * {transform: translate(0, -50%);} /* 往 Y 方向移動 -50% 元素本身高度 */
.c * {
transform: translate(0, -50%);
line-height: 70px; /* 設定行高 */
vertical-align: middle; /* 垂直對齊 */
}
</style>
使用這種做法如果遇到「多行」情境,在子元素尺寸不同或字體大小不同的情況下,往上平移的數值就需要與 line-height
相同,才不會發生位移後與行高不同而無法垂直置中,下方範例會展示這種差異。
<!-- HTML 程式碼 -->
top: 50%; 搭配 translate: 0 -50%;
<div class="a"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
top: 70px; 搭配 transform: translate(0, -50%); 和行高、垂直對齊
<div class="b"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
<!-- CSS 程式碼 -->
<style>
div {
height: 200px;
width: 200px;
border: 1px solid #000;
margin: 5px 0 20px;
}
div * {
margin: 0;
padding: 0;
border: 1px solid #000;
background: #f99;
display: inline-block;
position: relative;
}
.a * {
top: 50%;
translate: 0 -50%;
}
.b * {
top: 70px; /* 數值和行高相同 */
line-height: 70px; /* 設定行高 */
vertical-align: middle;
transform: translate(0, -50%);
}
</style>
同時水平垂直置中
參考「CSS 水平置中技巧」教學內容,可以將水平置中和垂直置中的技巧整合在一起,就能實現同時水平垂直置中的效果,下方範例列出三種做法:
<!-- HTML 程式碼 -->
text-align: center; 搭配 line-height 與 vertical-align: middle;
<div class="a"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
flex 排版
<div class="b"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
grid 排版
<div class="c"><h1>Apple</h1> <h2>Banana</h2> <h3>oxxo</h3> <h4>Papaya</h4></div>
<!-- CSS 程式碼 -->
<style>
div {
height: 100px;
width: 450px;
border: 1px solid #000;
margin: 5px 0 20px;
}
div * {
width: 100px;
margin: 0;
border: 1px solid #000;
background: #fa6;
height: 50px;
}
.a {
text-align: center; /* 行內容器水平置中 */
line-height: 100px; /* 行高 100px */
}
.a * {
display: inline-block; /* 修改顯示類型 */
line-height: 50px; /* 所有內容行高 50px,但會垂直對齊最大行高 100px */
vertical-align: middle; /* 垂直置中對齊 */
}
.b {
display: flex; /* flex 排版 */
align-items: center; /* 垂直置中 */
align-content: center; /* 多行垂直置中 */
justify-content: center; /* 水平置中 */
}
.c {
display: grid; /* grid 排版 */
grid-template-columns: repeat(4, 100px); /* 一列四欄,每一欄 100px */
align-content: center; /* 垂直置中 */
justify-content: center; /* 水平置中 */
}
</style>
小結
垂直置中是 CSS 排版裡的重要技巧,許多選單、banner 或內容時常會應用到垂直置中進行排版,透過這篇文章,對於 CSS 垂直置中 就能有更深一層的認識,也能更妥善的應用在網頁排版當中。
延伸閱讀:CSS 水平置中技巧
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~