垂直置中技巧
这篇教学会介绍多种 CSS“垂直置中”的实用技巧,运用行高、定位、对齐以及 Flex 弹性排版、Grid 网格排版等方式,分别将行内容器 ( 单行文字、多行文字等 ) 和区块容器 ( h1~h6、div 等 ) 套用垂直置中的效果,最后还会示范同时垂直水平置中的做法。
延伸阅读:CSS 水平置中技巧
快速导览:
垂直置中技巧列表
正规作法 ( 推荐 )
所谓的正规作法,表示单纯依靠 CSS 所提供的垂直置中功能以及基本原理,就能实现垂直置中效果,这些做法较为弹性且符合大多数情境,是较为推荐的方法。
垂直置中技巧 单行 多行 作用元素 line-height O X inline-*vertical-align O O inline-*、table-*,需搭配line-heightalign-self ( grid ) O X 网格项目 align-items ( flex、grid ) O X 弹性容器、网格容器 align-content ( flex、grid ) X O 弹性容器、网格容器,需搭配 align-items非正规作法
非正规的做法表示透过两三种样式属性互相搭配,使得元素的位置看起来像是垂直置中,由于必须使用多种定位和排版方式,且有时还得搭配手动设定数值,使用后较不弹性且容易出错,建议在上述正规作法都无法实现时,再考虑透过这些方式处理垂直置中。
垂直置中技巧 单行 多行 作用元素 padding + transform O O inline-*,需搭配手动计算或line-heighttop + 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 水平置中技巧
微信扫码关注
抖音扫码关注