實現css水平垂直居中的方法有很多,在這里我簡單的說下四種比較常用的方法:
1.使用CSS3中的Flex布局
對於flex,我們要了解的是它是一個display的屬性,而且必須要給他的父元素設置flex屬性(flex必須配合絕對定位使用!!!!!),除了設置display:flex之外,還有另外兩個屬性需要設置,分別是justify-content和align-items,他們的意思分別是水平居中和垂直居中。HTML+CSS代碼如下:
body { position: absolute; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; } .parentNode { width: 400px; height: 400px; background: #f00; }
<body> <div class="parentNode"></div> </body>
當需求改變時,比如我們要在此div里面嵌套一個div,根據我上面提到的,要想子DIV垂直水平居中,我們也要給父DIV同樣這樣設置
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> * { margin: 0; padding: 0; } body { position: absolute; // flex必須配合absolute使用才會生效 width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; } .parentNode { width: 400px; height: 400px; background: #f00; position: relative; // 這里必須用relative 原因是 相對於 body這個父標簽定位 如果用absolute會找上級的relative,如果沒有,就到頂級的document display: flex; justify-content: center; align-items: center; } .childNode { width: 200px; height: 200px; background: #fff; } </style> </head> <body> <div class="parentNode"> <div class="childNode"></div> </div> </body> </html>
2.使用CSS3中的transform
.parentNode { width: 400px; height: 400px; background: #f00; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); }
3.當你知道元素的width與height時,使用CSS2中的最普通不過的margin
.parentNode { width: 400px; height: 400px; background: #f00; position: absolute; left: 50%; top: 50%; margin: -200px 0 0 -200px; }
4.使用比較特殊的margin:auto
.parentNode { width: 400px; height: 400px; background: #f00; overflow: auto; margin: auto; // 在標准流的情況下,讓 margin-top 以及 margin-bottom 都為0 position: absolute; top: 0; left: 0; bottom: 0; right: 0; // 使瀏覽器對其元素所在的區域內重新渲染,四個值都設為0目的是讓整個窗口都為該元素的重新渲染區域,之后margin-top以及margin-bottom都相等 }
現在讓我們來使用強大的SASS重構一下這幾個樣式,先拿flex開刀吧,
@mixin center { display: flex; justify-content: center; align-items: center; } body { position: absolute; width: 100%; height: 100%; @include center;
.parentNode { width: 400px; height: 400px; background: #f00; position: relative; @include center;
.childNode { width: 200px; height: 200px; background: #fff; } } }
如果你的整個網站中有幾處小樣式類似,比如顏色,字體等,在 Sass 可以使用"$"變量來統一處理,那么這種選擇還是不錯的。但當你的樣式變得越來越復雜,需要重復使用大段的樣式時,使用變量就無法達到我們目了。這個時候 Sass 中的混合宏就會變得非常有意義,@mixin 是用來聲明混合宏的關鍵詞,有點類似 CSS 中的 @media、@font-face 一樣。center 是混合宏的名稱。大括號里面是復用的樣式代碼。@include為調用混合宏。除了聲明一個不帶參數的混合宏之外,還可以在定義混合宏時帶有參數,並且在里面還可以寫更加復雜的邏輯。
下面我將會用到if else語句以及@mixin混合宏來封裝我們上面的第2,3,4方法。
我們的思路是先將DIV的左上角絕對定位到容器的中心位置,然后為 mixin 添加兩個可選參數($width,$height),分別代表元素的寬高,如果傳遞了參數,那么就使用負向 margin
的方法實現居中;如果沒有傳遞參數,就使用 CSS3的transform
的方法。
/** * 為子元素設定定位上下文 */ .parent { position: relative; } /** * 讓子元素絕對居中於父容器 * 沒有向 Sass mixin 傳遞寬和高,使用 CSS transform 屬性實現居中效果 */ .child-with-unknown-direction { @include center; } /** * 讓子元素絕對居中於父容器 * 向 Sass mixin 傳遞了寬度,所以就使用負向 margin 處理水平位置, * 使用 CSS transform translateY 處理垂直位置 */ .child-with-known-width { @include center(400px); } /** * 讓子元素絕對居中於父容器 * 向 Sass mixin 傳遞了高度,所以就使用負向 margin 處理垂直位置, * 使用 CSS transform translateX 處理水平位置 */ .child-with-known-height { @include center($height: 400px); } /** * 讓子元素絕對居中於父容器 * 向 Sass mixin 傳遞了高度和寬度,所以就使用負向 margin 處理水平和垂直位置 */ .child-with-known-direction { @include center(400px, 400px); }
現在我們開始封裝@mixin,由上面的CSS分析知,要實現居中必須先讓元素絕對定位
@mixin center($width: null, $height: null) { position: absolute; top: 50%; left: 50%; }
然后根據下面的邏輯搭建@mixin的骨架
width | height | solution |
---|---|---|
null | null | translate |
defined | defined | margin |
defined | null | margin-left + translateY |
null | defined | margin-right + translateX |
@mixin center($width:null,$height:null){ display: flex; justify-content: center; align-items: center; @if $width and $height { // do margin } @else if not $width and not $height { // do transform translate(-50%,-50%) } @else if not $width { // do margin-top and transform translateX } @else { // do margin-left and transform translateY } }
最后我們把具體的代碼插入到不同的條件中去
@mixin center($width:null,$height:null){ position: absolute; top: 50%; left: 50%; @if $width and $height { // do margin width: $width; height: $height; margin: -($height / 2) #{0 0} -($width / 2); //這里如果直接寫 0 0 他會編譯為 margin: xx 0 xx 而不是 margin:xx 0 0 xx,所以用 #{0 0}
} @else if not $width and not $height { // do transform translate(-50%,-50%) transform: translate(-50%,-50); } @else if not $width { // do margin-top and transform translateX height: $height; margin-top: -(height / 2); transform: translateX(-50%); } @else { // do margin-left and transform translateY width: $width; margin-top: -(width / 2); transform: translateY(-50%); } }
最后我們可以通過Koala軟件離線編譯也可以通過http://www.sassmeister.com/在線編譯,下面是編譯好的結果
@charset "UTF-8"; /** * 為子元素設定定位上下文 */ .parent { position: relative; } /** * 讓子元素絕對居中於父容器 * 沒有向 Sass mixin 傳遞寬和高,使用 CSS transform 屬性實現居中效果 */ .child-with-unknown-direction { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50); } /** * 讓子元素絕對居中於父容器 * 向 Sass mixin 傳遞了寬度,所以就使用負向 margin 處理水平位置, * 使用 CSS transform translateY 處理垂直位置 */ .child-with-known-width { position: absolute; top: 50%; left: 50%; width: 400px; margin-top: -width/2; transform: translateY(-50%); } /** * 讓子元素絕對居中於父容器 * 向 Sass mixin 傳遞了高度,所以就使用負向 margin 處理垂直位置, * 使用 CSS transform translateX 處理水平位置 */ .child-with-known-height { position: absolute; top: 50%; left: 50%; height: 400px; margin-top: -height/2; transform: translateX(-50%); } /** * 讓子元素絕對居中於父容器 * 向 Sass mixin 傳遞了高度和寬度,所以就使用負向 margin 處理水平和垂直位置 */ .child-with-known-direction { position: absolute; top: 50%; left: 50%; width: 400px; height: 400px; margin: -200px 0 0 -200px; }