點燈坊

失くすものさえない今が強くなるチャンスよ

如何水平置中 ?

Sam Xiao's Avatar 2021-04-01

水平置中為實務上常見需求,CSS 可由多種方式實現。

Version

CSS 3

text-align: center

css000

使用最簡單直覺的 text-align: ceter 使 CSS 水平置中。

<template>
  <div class="box">
    CSS
  </div>
</template>

<style scoped>
.box {
  text-align: center;
}
</style>

第 8 行

.box {
  text-align: center;
}

設定父層 box style:

  • text-align: center<div> 為 block 會佔據一整行,直接使用 text-align: center 讓 content 水平置中於 <div>

margin: auto

width: fit-content

css001

水平置中另一個直覺思維就是使用 margin: auto 自動調整左右 margin 而水平置中。

但有個前提是 content 的 <div> 必須內縮與 content 同寬,margin: auto 才有動態調整 margin 空間。

<template>
  <div class="box">
    CSS
  </div>
</template>

<style scoped>
.box {
  width: fit-content;
  margin: auto;
}
</style>

第 8 行

.box {
  width: fit-content;
  margin: auto;
}

設定父層 box style:

  • width: fit-content:width 與 content 同寬,但仍維持其 block 特性,讓 margin: auto 有操作空間
  • margin: auto:相當於同時設定 margin-left: automargin-right: auto,使之能自動調整左右 margin 而水平置中

display: flex

center007

為了讓 <div> 與 content 同寬,另一個技巧是父層 box 引入 Flexbox 使子層 item 與 content 同寬。

<template>
  <div class="box">
    <div class="item">
      CSS
    </div>
  </div>
</template>

<style scoped>
.box {
  display: flex;
}

.item {
  margin: auto;
}
</style>

第 2 行

<div class="box">
  <div class="item">
    CSS
  </div>
</div>

父層使用 box,內層使用 item。

10 行

.box {
  display: flex;
}

設定父層 box style:

  • display: flex:為了要使 <div> 能與 conent 同寬有 margin 可操作水平置中

14 行

.item {
  margin: auto;
}

設定子層 item style:

  • margin: auto:由於 <div> 與 content 同寬,因此可自動調整左右 margin 而水平置中

Flexbox

justify-content: space-between

center002

Flexbox 亦有多種方式可水平置中,先討論從父層 box 處理。

<template>
  <div class="box">
    <div/>
    <div>CSS</div>
    <div/>
  </div>
</template>

<style scoped>
.box {
  display: flex;
  justify-content: space-between;
}
</style>

第 2 行

<div class="box">
  <div/>
  <div>CSS</div>
  <div/>
</div>

子層使用 3 個 item,兩旁為 dummy div。

第 9 行

.box {
  display: flex;
  justify-content: space-between;
}

設定父層 box style:

  • display: flex: 子層 item 使用 Flexbox
  • justify-content: space-between:原本為將剩餘寬度自動平分給 item 間剩餘空間,因為兩側 dummy div 沒有寬度,平分剩餘空間後 CSS 看起來像水平置中

justify-content: space-around

center004

CSS 水平置中,一樣使用 justify-content 系列。

<template>
  <div class="box">
    CSS
  </div>
</template>

<style scoped>
.box {
  display: flex;
  justify-content: space-around;
}
</style>

第 2 行

<div class="box">
  <div>CSS</div>
</div>

只需一個子層 item 即可。

第 7 行

.box {
  display: flex;
  justify-content: space-around;
}

設定父層 box style:

  • display: flex:子層 item 使用 Flexbox
  • justify-content: space-around:原本與 space-between 一樣將剩餘寬度自動平分給 item 間剩餘空間,但不同的是 space-around 會考慮 item 的前後空間,因此平分後看起來 CSS 像水平置中

justify-content: space-evenly

center006

CSS 水平置中,一樣使用 justify-content 系列。

<template>
  <div class="box">
    CSS
  </div>
</template>

<style scoped>
.box {
  display: flex;
  justify-content: space-evenly;
}
</style>

第 2 行

<div class="box">
  <div>CSS</div>
</div>

只需一個子層 item 即可。

第 8 行

.box {
  display: flex;
  justify-content: space-evenly;
}

設定父層 box style:

  • display: flex:層 item 使用 Flexbox
  • justify-content: space-evenly:原本與 space-between 一樣將剩餘寬度自動平分給 item 間剩餘空間,但不同的是 space-around 會考慮 item 的前後空間,因此平分後 CSS 看起來像水平置中

space-aroundspace-evenly 差異是儘管包含 item 前後空間,但 space-evenly 是真正 evenly 等寬,但 space-around item 間空間會是前後寬度的兩倍,但目前因為只有一個子層 item,因此 space-aroundspace-evenly 結果相同都是水平置中

justify-content: center

center005

CSS 水平置中,一樣使用 justify-content 系列。

<template>
  <div class="box">
    CSS
  </div>
</template>

<style scoped>
.box {
  display: flex;
  justify-content: center;
}
</style>

第 2 行

<div class="box">
  CSS
</div>

只需一個子層 item 即可。

第 7 行

.box {
  display: flex;
  justify-content: center;
}

設定父層 box style:

  • display: flex:子層 item 使用 Flexbox
  • justify-content: center:直接將 <div> 水平置中

flex-grow: 1

center003

CSS 水平置中,但在子層 item 處理。

<template>
  <div class="box">
    <div class="empty"/>
    <div>CSS</div>
    <div class="empty"/>
  </div>
</template>

<style scoped>
.box {
  display: flex;
}

.empty {
  flex-grow: 1;
}
</style>

第 2 行

<div class="box">
  <div class="empty"/>
  <div>CSS</div>
  <div class="empty"/>
</div>

需使用三個子層 item。

10 行

.box {
  display: flex;
}

設定父層 box style:

  • display: flex:子層 item 使用 Flexbox

14 行

.empty {
  flex-grow: 1
}

設定子層 empty style:

  • flex-grow: 1:表示空白部分剩餘 width 將由此 <div> 平分,因此看起來為水平置中

Fixed Position

center008

CSS 水平置中,但使用 fixed position 處理。

<template>
  <div class="box">
    CSS
  </div>
</template>

<style scoped>
.box {
  width: fit-content;
  position: fixed;
  left: 0;
  right: 0;
  margin: auto;
}
</style>

第 8 行

.box {
  width: fit-content;
  position: fixed;
  left: 0;
  right: 0;
  margin: auto;
}

設定父層 box style:

  • width: fit-content:width 與 content 同寬,但仍維持其 block 特性,讓 margin: auto 有操作空間
  • position: fixed:使用 fixed position
  • left: 0right: 0:要使用 margin: auto 水平置中,前提必須要有空間使其調整 margin,left: 0 於左側邊緣緊貼 browser,right: 0 於右側邊緣緊貼 browser,因此相當於架構出無形的矩形空間,只是受限於 width: fit-content 只顯示與 content 同寬部分,剩下空間可由 margin: auto 自由發揮而水平置中
  • margin: auto:自動調整左右 margin 而水平置中

Absolute Position

center009

CSS 水平置中,但使用 absolute position 處理。

<template>
  <div class="box">
    CSS
  </div>
</template>

<style scoped>
.box {
  width: fit-content;
  position: absolute;
  left: 0;
  right: 0;
  margin: auto;
}
</style>

第 8 行

.box {
  width: fit-content;
  position: absolute;
  left: 0;
  right: 0;
  margin: auto;
}

設定父層 box style:

  • width: fit-content:width 與 content 同寬,但仍維持其 block 特性,讓 margin: auto 有操作空間
  • position: absolute:使用 absolute position,因為其父層皆沒設定定位,相當於定位在 window
  • left: 0right: 0:要使用 margin: auto 水平置中,前提必須要有空間使其調整 margin,left: 0 於左側邊緣緊貼 browser,right: 0 於右側邊緣緊貼 browser,因此相當於架構出無形的矩形空間,只是受限於 width: fit-content 只顯示與 content 同寬部分,剩下空間可由 margin: auto 自由發揮而水平置中
  • margin: auto:自動調整左右 margin 而水平置中

Relative Position

center010

CSS 水平置中,改由父層 box 使用 relative position 處理。

<template>
  <div class="box">
    <div class="item">
      CSS
    </div>
  </div>
</template>

<style scoped>
.box {
  position: relative;
}

.item {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}
</style>

第 2 行

<div class="box">
  <div class="item">
    CSS
  </div>
</div>

需使用兩層 HTML。

10 行

.box {
  position: relative;
}

設定父層 box style:

  • position: relative:父層 box 使用 relative position,子層 absolute position 將以此層定位

14 行

.item {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}

設定子層 item style:

  • position: absolute:子層 item 使用 absolute position
  • left: 50%left 座標為 50%,此為 item 左側位置,並不算水平置中
  • transform: translateX(-50%):將 item 左移本身 width 的 50%,此時才算真正水平置中

Conclusion

  • CSS 擁有多種方式水平置中:text-align: centermargin: auto、Flexbox 、 Fixed Position 、 Absolute Position 與 Relative Position,可視實際需求靈活運用