垂直置中為實務上常見需求,CSS 可由多種方式實現。
Version
CSS 3
Flexbox
justify-content: space-between

Flexbox 亦有多種方式可垂直置中,先討論從父層 box 處理。
<template>
<div class="box">
<div/>
<div>CSS</div>
<div/>
</div>
</template>
<style scoped>
.box {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100vh;
}
</style>
第 2 行
<div class="box">
<div/>
<div>CSS</div>
<div/>
</div>
子層使用 3 個 item,兩旁為 dummy div。
10 行
.box {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100vh;
}
設定父層 box style:
display: flex:子層 item 使用 Flexbox 排列flex-direction: column:設定 main axis 為 column
justify-content: space-between:原本為將剩餘高度自動平分給 item 間剩餘空間,因為兩側 dummy div 沒有高度,平分剩餘空間後CSS看起來像垂直置中height: 100vh: 設定 box height
justify-content: space-around

CSS 垂直置中,一樣使用 justify-content 系列。
<template>
<div class="box">
CSS
</div>
</template>
<style scoped>
.box {
display: flex;
flex-direction: column;
justify-content: space-around;
height: 100vh;
}
</style>
第 8 行
.box {
display: flex;
flex-direction: column;
justify-content: space-around;
height: 100vh;
}
設定父層 box 的 style:
display: flex:子層 item 使用 Flexbox 排列flex-direction: column:設定 main axis 為 column,也因為 main axis 為 column,本來 Flexbox 會使<div>寬度由 content 決定,高度撐滿100vh,現在改成高度由 content 決定,高度撐滿一整列justify-content: space-around:原本與space-between一樣將剩餘高度自動平分給 item 間剩餘空間,但不同的是space-around會考慮 item 的前後空間,因此平分後看起來CSS像垂直置中
justify-content: space-evenly

CSS 垂直置中,一樣使用 justify-content 系列。
<template>
<div class="box">
CSS
</div>
</template>
<style scoped>
.box {
display: flex;
flex-direction: column;
justify-content: space-evenly;
height: 100vh;
}
</style>
第 8 行
.box {
display: flex;
flex-direction: column;
justify-content: space-evenly;
height: 100vh;
}
設定父層 box 的 style:
display: flex:子層 item 使用 Flexbox 排列justify-content: space-evenly:原本與space-between一樣將剩餘高度自動平分給 item 間剩餘空間,但不同的是space-evenly會考慮 item 的前後空間,因此平分後CSS看起來像垂直置中
space-around與space-evenly差異是儘管包含 item 前後空間,但space-evenly是真正evenly等高,但space-arounditem 間空間會是前後高度的兩倍
justify-content: center

CSS 垂直置中,一樣使用 justify-content 系列。
<template>
<div class="box">
CSS
</div>
</template>
<style scoped>
.box {
display: flex;
flex-direction: column;
justify-content: center;
height: 100vh;
}
</style>
第 8 行
.box {
display: flex;
flex-direction: column;
justify-content: center;
height: 100vh;
}
設定父層 box 的 style:
display: flex:子層 item 使用 Flexbox 排列flex-direction: column:設定 main axis 為 column,也因為 main axis 為 column,本來 Flexbox 會使<div>寬度由 content 決定,高度撐滿100vh,現在改成高度由 content 決定,寬度撐滿一整列justify-content: center:直接將<div>置中於 main axis,因為目前 main axis 為 column,相當於垂直置中height: 100vh:設定 box height
align-items: center

CSS 垂直置中,改用 align-items 系列。
<template>
<div class="box">
CSS
</div>
</template>
<style scoped>
.box {
display: flex;
align-items: center;
height: 100vh;
}
</style>
第 8 行
.box {
display: flex;
align-items: center;
height: 100vh;
}
設定父層 box 的 style:
display: flex:子層 item 使用 Flexbox 排列align-items: center:由於沒更改 flex-direction,因此目前 main axis 仍是 row,可使用align-items: center直接置中於 cross axis,相當於垂直置中height: 100vh:設定 box height
align-content: center

CSS 垂直置中,改用 align-content 系列。
<template>
<div class="box">
CSS
</div>
</template>
<style scoped>
.box {
display: flex;
flex-wrap: wrap;
align-content: center;
height: 100vh;
}
</style>
第 8 行
.box {
display: flex;
flex-wrap: wrap;
align-content: center;
height: 100vh;
}
設定父層 box 的 style:
display: flex:子層 item 使用 Flexbox 排列flex-wrap:啟動換列機制,會抑制align-items: stretch預設 stretch 整個父層 box 高度,僅收縮成與 content 同高,因此 flex line 也收縮不再與父層 box 同高align-content: center:因為 flex line 不再與父層 box 同高,因此align-content: center才有機會以 flex line 對父層 box 垂直置中height: 100vh:設定 box height
flex-grow: 1

CSS 垂直置中,但在子層 item 處理。
<template>
<div class="box">
<div class="empty"/>
<div>CSS</div>
<div class="empty"/>
</div>
</template>
<style scoped>
.box {
display: flex;
flex-direction: column;
height: 100vh;
}
.empty {
flex-grow: 1;
}
</style>
第 2 行
<div class="box">
<div class="empty"/>
<div>CSS</div>
<div class="empty"/>
</div>
需使用三個子層 item。
10 行
.box {
display: flex;
flex-direction: column;
height: 100vh;
}
設定父層 box 的 style:
display: flex:子層 item 使用 Flexbox 排列flex-direction: column:設定 main axis 為 columnheight: 100vh:設定 box height
16 行
.empty {
flex-grow: 1;
}
flex-grow: 1:表示空白部分剩餘 height 將由此<div>平分,因此看起來為垂直置中
Fixed Position

CSS 垂直置中,但使用 fixed position 處理。
<template>
<div class="box">
CSS
</div>
</template>
<style scoped>
.box {
height: fit-content;
position: fixed;
top: 0;
bottom: 0;
margin: auto;
outline: 1px solid black;
}
</style>
第 8 行
.box {
height: fit-content;
position: fixed;
top: 0;
bottom: 0;
margin: auto;
outline: 1px solid black;
}
設定父層 box style:
height: fit-content:height 與 content 同高,但仍維持其 block 特性,讓margin: auto有操作空間position: fixed:使用 fixed positiontop: 0、bottom: 0:要使用margin: auto垂直置中,前提必須要有空間使其調整 margin,top: 0於上側邊緣緊貼 browser,bottom: 0於下側邊緣緊貼 browser,因此相當於架構出無形的矩形空間,只是受限於height: fit-content只顯示與 content 同高部分,剩下空間可由margin: auto自由發揮而垂直置中margin: auto:自動調整上下 margin 而垂直置中outline: 1px solid black:為了視覺顯示方框,實務上可不使用
Absolute Position

CSS 垂直置中,但使用 absolute position 處理。
<template>
<div class="box">
CSS
</div>
</template>
<style scoped>
.box {
height: fit-content;
position: absolute;
top: 0;
bottom: 0;
margin: auto;
outline: 1px solid black;
}
</style>
第 8 行
.box {
height: fit-content;
position: absolute;
top: 0;
bottom: 0;
margin: auto;
outline: 1px solid black;
}
設定父層 box style:
height: fit-content:height 與 content 同高,但仍維持其 block 特性,讓margin: auto有操作空間position: absolute:使用 absolute position,因為其父層皆沒設定定位,相當於定位在windowtop: 0、bottom: 0:要使用margin: auto垂直置中,前提必須要有空間使其調整 margin,top: 0於上側邊緣緊貼 browser,bottom: 0於下側邊緣緊貼 browser,因此相當於架構出無形的矩形空間,只是受限於height: fit-content只顯示與 content 同高部分,剩下空間可由margin: auto自由發揮而垂直置中margin: auto:自動調整上下 margin 而垂直置中outline: 1px solid black:為了視覺顯示方框,實務上可不使用
Relative Position

CSS 垂直置中,改由父層 box 使用 relative position 處理。
<template>
<div class="box">
<div class="item">
CSS
</div>
</div>
</template>
<style scoped>
.box {
position: relative;
height: 100vh;
}
</style>
第 2 行
<div class="box">
<div class="item">
CSS
</div>
</div>
需使用兩層 HTML。
10 行
.box {
position: relative;
height: 100vh;
}
設定父層 box style:
position: relative:父層 box 使用 relative position,子層 absolute position 將以此層定位height: 100vh:設定 height 為整個 browser 高度
水平置中時不必設定
width,因為 block 預設就是佔據一整列,但height預設只是 content 高度,因此要特別設定才能垂直置中
15 行
.item {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
設定子層 item style:
position: absolute:子層 item 使用 absolute positiontop: 50%:top座標為50%,此為item上側位置,並不算垂直置中transform: translateY(-50%):將item上移本身 height 的50%,此時才算真正垂直置中
Conclusion
- CSS 擁有多種方式垂直置中:Flexbox 、 Fixed Position 、 Absolute Position 與 Relative Position,可視實際需求靈活運用