如何只用CSS作到徹底居中

咱們都知道 margin:0 auto; 的樣式能讓元素水平居中,而 margin: auto; 卻不能作到垂直居中……直到如今。可是,請注意!想讓元素絕對居中,只須要聲明元素高度,而且附加如下樣式,就能夠作到:css

1
2
3
4
5
.Absolute-Center {
   margin : auto ;
   position : absolute ;
   top : 0 ; left : 0 ; bottom : 0 ; right : 0 ;
}

我並非第一個發現這種方法的人(不過我仍是敢把它叫作「徹底居中」),它有多是種很是廣泛的技巧。但大多數介紹垂直居中的文章中並無提到過這種方法。若是不是瀏覽這篇文章的評論,我甚至根本就不會發現這個辦法。html

上面那篇文章的評論欄中,Simon提供了一個jsFiddle的連接,其餘的方法相比之下就相形見絀了。(Priit也在評論欄中提到了一樣的方法)。深刻研究了一番以後,我又用某些關鍵詞找到了記載這種方法的三個網站:站點一站點二站點三web

之前從未用過這種方法的我想試試,看看這種」徹底居中」的方法到底有多麼神奇。 好處:瀏覽器

  • 跨瀏覽器,兼容性好(無需hack,可兼顧IE8~IE10)
  • 無特殊標記,樣式更精簡
  • 自適應佈局,可使用百分比和最大最小高寬等樣式
  • 居中時不考慮元素的padding值(也不須要使用box-sizing樣式)
  • 佈局塊能夠自由調節大小
  • img的圖像也可使用

同時注意:ide

  • 必須聲明元素高度
  • 推薦設置overflow:auto;樣式避免元素溢出,顯示不正常的問題
  • 這種方法在Windows Phone上不起做用

瀏覽器支持:Chrome、Firefox、Safari、Mobile Safari、IE8-10。 「徹底居中」經測試能夠完美地應用在最新版本的Chrome、Firefox、Safari、Mobile Safari中,甚至也能夠運行在IE8~IE10上佈局

 

對照表

「徹底居中」並非本篇文章中惟一的選項。要作到垂直居中,還存在着其餘方法,各有各的長處。採起什麼樣的方法,取決於你所支持的瀏覽器,以及現有標籤的結構。下面這張對照表可以幫你選出最符合你須要的方法。性能

所用樣式測試

支持的瀏覽器字體

是否 響應式flex

內容溢出後的樣式

resize:both

高度可變

主要缺陷

Absolute

現代瀏覽器&IE8+

會致使容器溢出

是*

‘可變高度’的特性不能跨瀏覽器

負margin值

全部

帶滾動條

大小改變後再也不居中

不具備響應式特性,margin值必須通過手工計算

Transform

現代瀏覽器&IE9+

會致使容器溢出

妨礙渲染

Table-Cell

現代瀏覽器&IE8+

撐開容器

會加上多餘的標記

Inline-Block

現代瀏覽器&IE8+&IE7*

撐開容器

須要使用容器包裹和hack式的樣式

Flexbox

現代瀏覽器&IE10+

會致使容器溢出

須要使用容器包裹和廠商前綴(vendor prefix)

說明

在研究了規範和文檔後,我總結出了「徹底居中」的工做原理:

  1. 在普通文檔流裏,margin: auto; 的意思是設置元素的margin-top和margin-bottom爲0。

W3.org :? If ‘margin-top’, or ‘margin-bottom’ are ‘auto’, their used value is 0.

2. 設置了position: absolute; 的元素會變成塊元素,並脫離普通文檔流。而文檔的其他部分照常渲染,元素像是不在原來的位置同樣。 Developer.mozilla.org :? …an element that is positioned absolutely is taken out of the flow and thus takes up no space

3. 設置了top: 0; left: 0; bottom: 0; right: 0; 樣式的塊元素會讓瀏覽器爲它包裹一層新的盒子,所以這個元素會填滿它相對父元素的內部空間,這個相對父元素能夠是是body標籤,或者是一個設置了position: relative; 樣式的容器。 Developer.mozilla.org :? For absolutely positioned elements, the top, right, bottom, and left properties specify offsets from the edge of the element’s containing block (what the element is positioned relative to).

4. 給元素設置了寬高之後,瀏覽器會阻止元素填滿全部的空間,根據margin: auto; 的要求,從新計算,幷包裹一層新的盒子。 Developer.mozilla.org :? The margin of the [absolutely positioned] element is then positioned inside these offsets.

5. 既然塊元素是絕對定位的,又脫離了普通文檔流,所以瀏覽器在包裹盒子以前會給margin-top和margin-bottom設置一個相等的值。 W3.org :? If none of the three [top, bottom, height] are ‘auto’: If both ‘margin-top’ and ‘margin-bottom’ are ‘auto’, solve the equation under the extra constraint that the two margins get equal values.?AKA: center the block vertically

使用「徹底居中」,有意遵守了標準margin: auto; 樣式渲染的規定,因此應當在與標準兼容的各類瀏覽器中起做用。

 

對齊

容器內對齊

使用「徹底居中」,就能夠在一個設置了position: relative的容器中作到徹底居中元素了! (居中例子,請前往英文原文查看)

1
2
3
4
5
6
7
8
9
10
11
12
.Center-Container {
   position : relative ;
}
 
.Absolute-Center {
   width : 50% ;
   height : 50% ;
   overflow : auto ;
   margin : auto ;
   position : absolute ;
   top : 0 ; left : 0 ; bottom : 0 ; right : 0 ;
}

接下來的示例會假設已經包含了如下樣式,而且以逐步添加樣式的方式提供不一樣的特性。

 

在可視區域內居中

想要使內容區在可視區域內居中麼?設置position: fixed樣式,並設置一個較高的z-index值,就能夠作到。

1
2
3
4
.Absolute-Center.is-Fixed {
   position : fixed ;
   z-index : 999 ;
}

移動版Safari的說明:若是外面沒有一層設置position: relative的容器,內容區會以整個文檔的高度的中心點爲基準居中,而不是以可視區域的高度中心點爲基準居中。

 

偏移值

若是須要添加固定的標題,或者其餘帶偏移樣式的元素,能夠直接把相似top: 70px; 的樣式寫進內容區域的樣式中。一旦聲明瞭margin: auto; 的樣式,內容塊的top left bottom right的屬性值也會同時計算進去。

若是想讓內容塊在貼近側邊的過程當中保持水平居中,可使用right: 0; left: auto; 讓內容貼在右側,或者使用left: 0; right: auto; 使內容貼在左側。

1
2
3
4
.Absolute-Center.is-Fixed {
   position : fixed ;
   z-index : 999 ;
}

 

帶響應式

使用absolute的最大好處就是能夠完美地使用帶百分比的寬高樣式!就算是min-width/max-width或者min-height/max-height也可以有如預期般的表現。

再進一步加上padding樣式的話,absolute式的徹底居中也絲絕不會破壞!

1
2
3
4
5
6
7
.Absolute-Center.is-Responsive {
   width : 60% ;
   height : 60% ;
   min-width : 200px ;
   max-width : 400px ;
   padding : 40px ;
}

 

帶溢出內容

內容區高度大於可視區域或者一個position: relative的容器,其內容可能會溢出容器,或被容器截斷。只要內容區域沒有超出容器(沒有給內容容器預留padding的話,能夠設置max-height: 100%;的樣式),那麼容器內就會產生滾動條。

1
2
3
.Absolute-Center.is-Overflow {
   overflow : auto ;
}

 

大小可調整

使用其餘樣式,或者使用JavaScript調整內容區的大小,也是不用手動從新計算的!若是設置了resize的樣式,甚至可讓用戶自行調節內容區域的大小。 「徹底居中」法,不管內容區怎麼改變大小,都會保持居中。

設置了min-/max- 開頭的屬性能夠限制區塊的大小而不用擔憂撐開容器。

1
2
3
4
5
6
7
8
.Absolute-Center.is-Resizable {
   min-width : 20% ;
   max-width : 80% ;
   min-height : 20% ;
   max-height : 80% ;
   resize: both ;
   overflow : auto ;
}

若是不設置resize: both的樣式,能夠設置transition樣式平滑地在大小間切換。必定要記得設置overflow: auto樣式,由於改變大小後的容器高寬頗有可能會小於內容的高寬。 「徹底居中」法是惟一一種能支持使用resize: both樣式的方法。

使用注意:

  • 須要設置max-width/max-height給內容區域留足夠的空間,否則就有可能使容器溢出。
  • resize屬性不支持移動版瀏覽器和IE8-10,若是用戶體驗很重要的話,請確保用戶能夠有其餘替代方法來改變大小。
  • 同時使用resize樣式和transition會使用戶在開始改變大小時產生等於transition效果時間等長的延時。

 

圖像

圖像也一樣有效!提供相應的class,並指定樣式 height: auto; ,就獲得了一張隨着容器改變大小的響應式圖片。

請注意,height: auto; 樣式雖然對圖片有效,若是沒有用到了後面介紹的‘可變高技巧’,則會致使普通內容區域伸長以適應容器長度。

瀏覽器頗有多是根據渲染結果填充了圖像高度值,因此在測試過的瀏覽器中,margin: auto; 樣式就像是聲明瞭固定的高度值通常正常工做。

HTML:

1
< img src = "http://placekitten.com/g/500/200" alt = "" />

CSS:

1
2
3
4
5
6
7
8
.Absolute-Center.is-Image {
   height : auto ;
}
 
.Absolute-Center.is-Image img {
   width : 100% ;
   height : auto ;
}

 

可變高度

「徹底居中」法的確須要聲明容器高度,可是高度受max-height樣式的影響,也能夠是百分比。這很是適合響應式的方案,只須要設置好帶溢出內容就行。

另外一種替代方案是設置display: table樣式居中,,無論內容的長度。這種方法會在一些瀏覽器中產生問題(主要是IE和Firefox)。我在ELL Creative的朋友Kalley寫了一個基於Modernizr 的測試,能夠用來檢查瀏覽器是否支持這種居中方案。如今這種方法能夠作到漸進加強。

注意要點: 這種方法會破壞瀏覽器兼容性,若是Modernizr測試不能知足你的需求,你可能須要考慮其餘的實現方案。

  • 與大小可調整技術是不兼容的
  • Firefox/IE8中使用display: table,內容區在垂直方向靠上,水平方向仍然居中。
  • IE9/10中使用display: table,內容區會跑到左上角。
  • 移動版Safari中內容區是水平對齊的,可是若是使用了百分比的寬度,水平方向上會稍稍偏離中心。

Javascript:

1
2
3
4
/* Modernizr Test for Variable Height Content */
Modernizr.testStyles( '#modernizr { display: table; height: 50px; width: 50px; margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; }' , function(elem, rule) {
   Modernizr.addTest( 'absolutecentercontent' , Math.round(window.innerHeight / 2 - 25 ) === elem.offsetTop);
});

CSS:

1
2
3
4
.absolutecentercontent .Absolute-Center.is-Variable {
   display : table;
   height : auto ;
}

 

其餘方法

「徹底居中」法是解決居中問題的好方法,同時也有許多能夠知足不一樣需求的其餘方法。最多見的,推薦的方法有負margin值、transform法、table-cell法、inline-block法、以及如今出現的Flexbox法,這些方法其餘文章都有深刻介紹,因此這裏只會稍稍說起。

 

負margin值

這或許是最經常使用的方法。若是知道了各個元素的大小,設置等於寬高一半大小的負margin值(若是沒有使用box-sizing: border-box樣式,還須要加上padding值),再配合top: 50%; left: 50%;樣式就會使塊元素居中。

須要注意的是,這是按照預想狀況也能在工做在IE6-7下的惟一方法。

1
2
3
4
5
6
7
8
9
.is-Negative {
         width : 300px ;
         height : 200px ;
         padding : 20px ;
         position : absolute ;
         top : 50% ; left : 50% ;
         margin-left : -170px ; /* (width + padding)/2 */
         margin-top : -120px ; /* (height + padding)/2 */
}

好處:

  • 瀏覽器兼容性很是好,甚至支持IE6-7
  • 須要的編碼量不多

同時注意:

  • 這是個非響應式的方法,不能使用百分比的大小,也不能設置min-/max-的最大值最小值。
  • 內容可能會超出容器
  • 須要爲padding預留空間,或者須要使用box-sizing: border-box樣式。

 

transform法

和「徹底居中」法的好處同樣,簡單有效,同時支持可變高度。爲內容指定帶有廠商前綴的transform: translate(-50%,-50%)和top: 50%; left: 50%;樣式就可讓內容塊居中。

1
2
3
4
5
6
7
8
9
.is-Transformed {
   width : 50% ;
   margin : auto ;
   position : absolute ;
   top : 50% ; left : 50% ;
   -webkit-transform: translate( -50% , -50% );
       -ms-transform: translate( -50% , -50% );
           transform: translate( -50% , -50% );
}

好處:

  • 內容高度可變
  • 代碼量小

同時注意:

  • 不支持IE8
  • 須要寫廠商前綴
  • 會和其餘transform樣式有衝突
  • 某些狀況下的邊緣和字體渲染會有問題

 

table-cell法

這種多是最好的方法,由於高度能夠隨內容改變,瀏覽器支持也不差。主要缺陷是會產生額外的標籤,每個須要居中的元素須要三個額外的HTML標籤。

HTML:

1
2
3
4
5
6
7
<div class= "Center-Container is-Table" >
   <div class= "Table-Cell" >
     <div class= "Center-Block" >
     <!-- CONTENT -->
     </div>
   </div>
</div>

CSS:

1
2
3
4
5
6
7
8
9
.Center-Container.is-Table { display : table; }
.is-Table .Table-Cell {
   display : table-cell ;
   vertical-align : middle ;
}
.is-Table .Center-Block {
   width : 50% ;
   margin : 0 auto ;
}

好處:

  • 內容高度可變
  • 內容溢出則能自動撐開父元素高度
  • 瀏覽器兼容性好

同時注意:

  • 須要額外的HTML標籤

inline-block法

迫切須要的方法:inline-block法居中。基本方法是使用 display: inline-blockvertical-align: middle樣式和僞元素讓內容塊在容器中居中。個人實現用到了幾個在其餘地方見不到的新技巧解決了一些問題。

內容區聲明的寬度不能大於容器的100% 減去0.25em的寬度。就像一段帶有長文本的區域。否則,內容區域會被推到頂端,這就是使用:after僞類的緣由。使用:before僞類則會讓元素有100%的大小!

若是內容塊須要儘量大地佔用水平空間,能夠爲大容器加上max-width: 99%;樣式,或者考慮瀏覽器和容器寬度的狀況下使用max-width: calc(100% – 0.25em) 樣式。

這種方法和table-cell的大多數好處相同,不過最初我放棄了這個方法,由於它更像是hack。無論這一點的話,瀏覽器支持很不錯,並且也被證明是很流行的方法。

HTML:

1
2
3
4
5
< div class = "Center-Container is-Inline" >
   < div class = "Center-Block" >
     <!-- CONTENT -->
   </ div >
</ div >

CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.Center-Container.is-Inline {
   text-align : center ;
   overflow : auto ;
}
 
.Center-Container.is-Inline:after,
.is-Inline .Center-Block {
   display : inline- block ;
   vertical-align : middle ;
}
 
.Center-Container.is-Inline:after {
   content : '' ;
   height : 100% ;
   margin-left : -0.25em ; /* To offset spacing. May vary by font */
}
 
.is-Inline .Center-Block {
   max-width : 99% ; /* Prevents issues with long content causes the content block to be pushed to the top */
   /* max-width: calc(100% - 0.25em) /* Only for IE9+ */
}

好處:

  • 內容高度可變
  • 內容溢出則能自動撐開父元素高度
  • 瀏覽器兼容性好,甚至能夠調整支持IE7

同時注意:

  • 須要額外容器
  • 依賴於margin-left: -0.25em的樣式,作到水平居中,須要爲不一樣的字體大小做調整
  • 內容區聲明的寬度不能大於容器的100% 減去0.25em的寬度

 

Flexbox法

CSS將來發展的方向就是採用Flexbox這種設計,解決像垂直居中這種共同的問題。請注意,Flexbox有不止一種辦法居中,他也能夠用來分欄,並解決奇奇怪怪的佈局問題。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.Center-Container.is-Flexbox {
   display : -webkit-box;
   display : -moz-box;
   display : -ms-flexbox;
   display : -webkit-flex;
   display : flex;
   -webkit-box-align: center ;
      -moz-box-align: center ;
      -ms-flex-align: center ;
   -webkit-align-items: center ;
           align-items: center ;
   -webkit-box-pack: center ;
      -moz-box-pack: center ;
      -ms-flex-pack: center ;
   -webkit-justify- content : center ;
           justify- content : center ;
}

好處:

  • 內容能夠是任意高寬,溢出也能表現良好
  • 能夠用於各類高級佈局技巧

同時注意: 不支持IE8-9

  • 須要在body上寫樣式,或者須要額外容器
  • 須要各類廠商前綴兼容現代瀏覽器
  • 可能有潛在的性能問題

 

最後的建議

各項技術都有各自的好處,採起什麼樣的方法,取決於你所支持的瀏覽器,以及現有標籤的結構。請使用上面提供對照表幫你選出最符合你須要的方法。

「徹底居中」法簡單方便,迅速及時。之前使用負Margin值的地方,均可以使用Absolute居中。無需繁瑣的數學計算,無需額外標籤,並且能夠隨時改變大小。

若是網站須要可變高度的內容,並且同時照顧到瀏覽器兼容性的話,能夠嘗試table-cell和inline-block技術,若是想嘗試新鮮事物的話,可使用Flexbox,並享受這種高級技術帶來的好處。

相關文章
相關標籤/搜索