Css - 水平置中、垂直置中的各種方法
在網頁排版的時候經常會遇到需要水平(左右)、垂直(上下)置中的排版設計,同時也是前端面試的時候經常被問到的基礎考題。
可以先判斷要置中的元素:
是行內元素(inline element)還是區塊元素(block element)
想要水平置中還是垂直置中(或兩者皆是)
來分別對應不同的 CSS 置中方法。
文字水平垂直置中
行內元素(例如:文字)的置中方式。
Flex
使用 flexbox 排版 display: flex
搭配屬性 justify-content
(主軸對齊方式)、 align-items
(交錯軸對齊方式)來將 div 裡的文字置中。
- 在父層(container)
div
下display: flex;
水平置中
- 加上
justify-content: center;
屬性來讓主軸(水平)置中對齊
垂直置中
- 加上
align-items: center;
屬性來讓交錯軸(垂直)置中對齊
水平垂直置中
綜合以上即可達到水平、垂直置中:
div {
display: flex;
justify-content: center; /* 水平置中 */
align-items: center; /* 垂直置中 */
}
Line-height & Text-align
text-align
大家應該不陌生,設定文字對齊方式 text-align: center;
來將文字水平置中。
line-height
的作用顧名思義就是設定了文字的行高,文字會放置在這一行空間的垂直置中位置。
假設文字的尺寸 (font-size) 是 12px,行高(line-height) 是 20px,那麼文字會被置於在高 20px 的行盒(line box)中,上下會各留有 4px 的距離。
水平置中
- 設定
text-align: center;
將文字水平置中
垂直置中
- 將
line-height
與div
設定同高,就可以做到單行文字垂直置中的效果
水平垂直置中
綜合以上即可達到水平、垂直置中:
div {
background: yellow;
width: 500px;
height: 100px;
line-height: 100px; /* 文字垂直置中 */
text-align: center; /* 文字水平置中 */
}
試著將文字反白可以看到行高是佔滿整個 div 的:
Table + Vertical-align
將要置中的元素當成 table-cell 就可以使用 vertical-align
樣式來將內容垂直置中。由於是文字所以一樣可以透過 text-align: center;
將文字水平置中。
水平置中
- 設定
text-align: center;
將文字水平置中
垂直置中
在父層下
display: table;
將元素轉為 table在子層下
display: table-cell;
水平垂直置中
綜合以上即可達到水平、垂直置中:
/* 父層 div */
.parent {
display: table;
}
/* 子層 p */
.child {
display: table-cell;
vertical-align: middle; /* 表格文字垂直置中 */
text-align: center; /* 表格文字垂直置中 */
}
div 水平垂直置中
Flex
使用 flexbox 排版 display: flex
搭配屬性 justify-content
(主軸對齊方式)、 align-item
(交錯軸對齊方式)來將父層 div 裡的子層 items 置中。
- 在父層(container)
div
下display: flex;
水平置中
- 加上
justify-content: center;
來讓主軸(水平)置中對齊
垂直置中
- 加上
align-items: center;
來讓交錯軸(垂直)置中對齊
水平垂直置中
綜合以上即可達到水平、垂直置中:
div {
display: flex;
justify-content: center; /* item 水平置中 */
align-items: center; /* item 垂直置中 */
}
Grid
在父層
div
(container) 下display: grid;
加上
place-items: center;
或是place-content: center;
來將子層div
水平、垂直置中排列
.parent {
display: grid;
place-items: center; /* 或使用 place-content: center; */
}
雖然 place-items: center;
和 place-content: center;
都可以用於將 Grid 佈局內的子元素水平和垂直置中,但在意義中仍有不同之處:
place-items
place-items
屬性是 align-items
和 justify-items
的簡寫
align-items
控制 Grid 容器內所有子元素在垂直方向上的對齊方式justify-items
控制 Grid 容器內所有子元素在水平方向上的對齊方式
place-items: center;
會將 Grid 容器內的所有子元素都水平和垂直置中對齊。
place-content
place-content
屬性是 justify-content
和 align-content
的簡寫
align-content
控制 Grid 容器內所有行的對齊方式justify-content
控制Grid容器內所有列的對齊方式
place-content: center;
會將 Grid 容器的內容(即子元素佔據的所有行和列)水平和垂直置中對齊。
Absolute Positioning & Transform
利用 position: absolute;
絕對定位,搭配 transform: translate(value, value);
將元素位移來達到水平、垂直置中。
先設定絕對定位:
在父層
div
下position: relative;
在子層
div
下position: absolute;
接著再增加下列 CSS 屬性來達到水平或是垂直置中:
水平置中
加上
left: 50%;
將子層div
左邊界設定在父層div
寬度一半的位置加上
transform: translateX(-50%)
將超過的部分修正回來
垂直置中
加上
top: 50%;
將子層div
上邊界設定在父層div
高度一半的位置加上
transform: translateY(-50%)
將超過的部分修正回來
水平垂直置中
綜合
top: 50%;
與left: 50%;
將子層div
置於父層div
高度與寬度一半的位置,但此時可以看到,元素並非位於畫面的正中間加上
transform: translate(-50%, -50%)
給予負值,將超過的 X 軸與 Y 軸部分修正回來
/* 父層 div */
.parent {
position: relative;
}
/* 子層 div */
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%)
}
margin auto
margin: auto
會將剩餘的空間平均分配給四周
這邊的 auto
意思是瀏覽器會自動將剩餘的空間平均分配,由於 margin 的預設值四邊都是 0,所以左右剩餘空間也會是一樣的,也就能達到水平置中的效果了。
auto
會將剩餘空間分配,因此 margin-left:auto
會使元素靠右擺放;margin-right:auto
則會使元素靠左擺放。水平置中 width + margin auto
在想要置中的元素(子層 div
):
設定寬度
width
:一定要設置寬度,避免該元素從左到右撐滿容器- 使用
max-width
是更理想的做法,可以避免當瀏覽器寬度小於元素寬度時出現 x 軸
- 使用
加上
margin: 0 auto;
將左右(水平)的外邊距設定為auto
:這代表瀏覽器會自動將剩餘的空間平均分配給左、右外邊距,於是就達成了水平置中的效果
.child {
max-width: 100px;
margin: 0 auto; /* 或使用 margin: auto; */
}
這邊將 margin: 0 auto;
寫成 margin: auto;
效果也是一樣的(水平置中),雖然後者比起前者多將垂直(上下)方向的外邊距也設定為 auto
,但並沒有達到垂直置中的效果。
換句話說,如果是想將元素垂直置中,即使按照上述的邏輯改為設定垂直方向的 margin: auto 0;
也無法達成垂直置中效果。
margin: auto
與 margin: 0 auto
的差異可以參考這篇:[CSS學習筆記] 關於margin: auto和margin:0 auto水平置中 | 我在路易莎的日子 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)為什麼 margin auto 無法達到垂直置中效果
這是由於 margin 在水平和垂直方向上的效果略有不同。
CSS 文件中 關於 margin 在水平方向上的作用:
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
If both 'margin-left' and 'margin-right' are 'auto', their used values are equal. This horizontally centers the element with respect to the edges of the containing block.
— 10.3.3 Block-level, non-replaced elements in normal flow
「包含塊(containing block)」的寬度是由 width 本身,加上左右 padding、左右 border、左右 margin 所組成。因此當 margin-left
和 margin-right
都設置為 auto
時,它們會平均分配剩餘的空間,這樣就實現了水平置中。
CSS 文件中 關於 margin 在垂直方向上的作用:
If 'margin-top', or 'margin-bottom' are 'auto', their used value is 0.
— 10.6.3 Block-level non-replaced elements in normal flow when 'overflow' computes to 'visible'
我們可以得到結論:
當
margin-left
和margin-right
都是 auto,則它們的值相等,進而使元素在容器中水平居中對齊當
margin-top
和margin-bottom
都是 auto,則它們的值都為 0,因此也無法使元素在容器中垂直居中對齊
水平垂直置中 margin auto + flex | grid
在父層
div
下display: flex | grid | inline-flex | inline-grid;
在子層
div
下margin: auto;
來達成水平、垂直置中的效果
那為什麼這邊的 margin: auto;
又對垂直置中有作用了呢?因為 flexbox 和 grid 的佈局系統讓元素的對齊和佈局更加靈活了,在這些佈局中 margin: auto;
可以用於實現元素的水平和垂直置中。
Flexbox:將
margin: auto;
用於 Flex 容器內的子元素,可以使子元素在垂直和水平方向上都居中對齊。Grid:將
margin: auto;
用於 Grid 容器內的子元素,可以使子元素在網格單元格中水平和垂直置中。
Ref
Subscribe to my newsletter
Read articles from Ya Chu directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by