CSS實現垂直居中


[TOC]

我們經常用 margin:0 auto 來實現水平居中,而一直認為 margin: auto 不能實現垂直居中……
實際上,實現垂直居中僅需要聲明元素的高寬和下面的CSS:

.Absolute-Center {  
    position: fixed;    /* 或 absolute */
    margin: auto;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

這種方式被稱為絕對居中(Absolute Centering)。

絕對居中(Absolute Centering)

優點:

  • 支持跨瀏覽器,包括IE8-IE10.
  • 無需其他特殊標記,CSS代碼量少
  • 支持百分比%屬性值和min-/max-屬性
  • 只用這一個類可實現任何內容塊居中
  • 不論是否設置padding都可居中(在不使用box-sizing屬性的前提下)
  • 內容塊可以被重繪。
  • 完美支持圖片居中。

缺點:

  • 必須聲明高度(查看可變高度Variable Height)。
  • 建議設置 overflow: auto 來防止內容越界溢出。
  • 在Windows Phone設備上不起作用。

工作機理:

  • 在普通內容流(normal content flow)中,margin: auto 的效果等同於 margin-top: 0;margin-bottom: 0
    W3C中寫道 If 'margin-top', or'margin-bottom' are 'auto', their used value is 0.

  • position: absolute 使絕對定位塊跳出了內容流,內容流中的其余部分渲染時絕對定位部分不進行渲染。
    Developer.mozilla.org: ...an element that is positioned absolutely is taken out of the flow and thustakes up no space

  • 為塊區域設置 top: 0; left: 0; bottom: 0; right: 0; 將給瀏覽器重新分配一個邊界框,此時該塊 block 將填充其父元素的所有可用空間,父元素一般為 body 或者聲明為 position: relative; 的容器。
    Developer.mozilla.org:For absolutely positioned elements, the top, right, bottom, and left propertiesspecify offsets from the edge of the element's containing block (what theelement is positioned relative to).

  • 給內容塊設置一個高度height或寬度width,能夠防止內容塊占據所有的可用空間,促使瀏覽器根據新的邊界框重新計算margin:auto
    Developer.mozilla.org: The margin of the[absolutely positioned] element is then positioned inside these offsets.

  • 由於內容塊被絕對定位,脫離了正常的內容流,瀏覽器會給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', solvethe equation under the extra constraint that the two margins get equal values.AKA: center the block vertically

這么看來, margin: auto 似乎生來就是為絕對居中(Absolute Centering)設計的,所以絕對居中(Absolute Centering)應該都兼容符合標准的現代瀏覽器。
簡而言之:絕對定位元素不在普通內容流中渲染,因此 margin: auto 可以使內容在通過 top: 0; left: 0; bottom: 0;right: 0; 設置的邊界內垂直居中。

幾種情況下的垂直居中

一、視口內(Within Viewport)

想讓內容塊一直停留在可視區域內,只需要將內容塊設置為 position: fixed; 並設置一個較大的z-index層疊屬性值。

.current-contaner {
    width: 50%;
    height: 50%;
    overflow: auto;

    position: fixed;
    z-index: 1000;
    margin: auto;
    top: 0; left: 0; bottom: 0; right: 0;

注: 注意:對MobileSafari,若內容塊不是放在設置為 position: relative; 的父容器中,內容塊將垂直居中於整個文檔,而不是可視區域內垂直居中。

二、容器內(Within Container)

當內容塊的父容器設置為 position: relative,使用下面的方式,可以使內容居中顯示於父容器。
t

.father-container {
    position: relative;
}

.current-contaner {
    width: 50%;
    height: 50%;
    overflow: auto;
    
    position: absolute;     /* 父容器設置為 position: relative */
    margin: auto;
    top: 0; left: 0; bottom: 0; right: 0;  
} 

container

三、偏移 / 側邊(Offset )

如果需要將內容塊固定在屏幕或者父容器內的左側或右側,並且保持內容塊垂直居中。使用 right: 0;left: auto; 固定於屏幕右側,左側同理。

.current-container {
    position: fixed;
    margin: auto;

    left: auto;     /* 也可以去掉 left: auto */
    right: 15px;

    top: 0;
    bottom: 0;
    background: #1daaea;
    padding: 30px;
}

四、響應式/自適應(Responsive)

絕對居中最大的優勢應該就是對百分比 % 形式的寬高支持的非常完美。甚至 min-width/max-width 和 min-height/max-height 這些屬性在自適應盒子內的表現也和預期很一致。

.absolute-center.responsive {  
  width: 60%;   
  height: 60%;  
  min-width: 200px;  
  max-width: 400px;  
  padding: 40px;  
}  

五、 溢出情況(Overflow)

.absolute-center.overflow {  
  overflow: auto;  
}  

六、重繪(Resizing)

你可以使用其他class類或JavaScript代碼來重繪內容塊同時保證居中,無須手動重新計算中心尺寸。當然,你也可以添加resize屬性來讓用戶拖拽實現內容塊的重繪。

絕對居中(Absolute Centering)可以保證內容塊始終居中,無論內容塊是否重繪。可以通過設置min-/max-來根據自己需要限制內容塊的大小,並防止內容溢出窗口/容器。

.Absolute-Center.is-Resizable {  
  min-width: 20%;  
  max-width: 80%;  
  min-height: 20%;  
  max-height: 80%;  
  resize: both;     // CSS3 支持的屬性,指定一個元素是否是由用戶調整大小的 {vertical | horizontal | both | none}
  overflow: auto;  
}  

如果不使用resize:both屬性,可以使用CSS3動畫屬性transition來實現重繪的窗口之間平滑的過渡。一定要設置overflow:auto;以防重繪的內容塊尺寸小於內容的實際尺寸這種情況出現。

絕對居中(AbsoluteCentering)是唯一支持resize:both屬性實現垂直居中的技術。

注意:

  • 要設置max-width/max-height屬性來彌補內容塊padding,否則可能溢出。

  • 手機瀏覽器和IE8-IE10瀏覽器不支持resize屬性,所以如果對你來說,這部分用戶體驗很必要,務必保證對resizing你的用戶有可行的退路。
    聯合使用resize 和 transition屬性會在用戶重繪時,產生一個transition動畫延遲時間。

七、圖片(Images)

絕對居中(AbsoluteCentering)也適用於圖片。對圖片自身應用class類或CSS樣式,並給圖片添加 height: auto 樣式,圖片會自適應居中顯示,如果外層容器可以resize則隨着容器的重繪,圖片也相應重繪,始終保持居中。

需要注意的是height:auto 雖然對圖片居中有用,但如果是在圖片外層的內容塊上應用了height:auto 則會產生一些問題:規則的內容塊會被拉伸填充整個容器。這時,我們可以使用可變高度(Variable Height)方式解決這個問題。
問題的原因可能是渲染圖片時要計算圖片高度,這就如同你自己定義了圖片高度一樣,瀏覽器得到了圖片高度就不會像其他情況一樣去解析margin:auto 垂直居中了。所以我們最好對圖片自身應用這些樣式而不是父元素。

八、可變高度(Variable Height)





其他垂直居中方法

一、負外邊距(Negative Margins)

如果塊元素尺寸(width 和 height)已知,可以通過以下方式讓內容塊居中於容器顯示:
外邊距 margin 取負數,大小為 width/height(不使用box-sizing: border-box時包括padding,)的一半,再加上 top: 50%; left: 50%;即可。

.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-IE7上也表現良好的方法。

優點:

  1. 良好的跨瀏覽器特性,兼容IE6-IE7。
  2. 代碼量少。

缺點:

  1. 不能自適應。不支持百分比尺寸和min-/max-屬性設置。
  2. 內容可能溢出容器。
  3. 邊距大小與padding,和是否定義box-sizing: border-box有關,計算需要根據不同情況。

二、變形(Transforms)

這是最簡單的方法,不近能實現絕對居中同樣的效果,也支持聯合可變高度方式使用。內容塊定義transform: translate(-50%,-50%)必須帶上瀏覽器廠商的前綴,還要加上 top: 50%; left: 50%;

.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%);  
}  

優點:

1) 內容可變高度
2)代碼量少

缺點:

1)IE8不支持
2)屬性需要寫瀏覽器廠商前綴
3)可能干擾其他transform效果
4)某些情形下會出現文本或元素邊界渲染模糊的現象

進一步了解transform實現居中的知識可以參考CSS-Tricks的文章《Centering PercentageWidth/Height Elements》

三、表格單元格(Table-Cell)

這可能是最好的居中實現方法,因為內容塊高度會隨着實際內容的高度變化,瀏覽器對此的兼容性也好。最大的缺點是需要大量額外的標記,需要三層元素讓最內層的元素居中。

<!-- HTML -->
<div class="center-container is-table">  
  <div class="table-cell">  
    <div class="center-block">  
    <!-- CONTENT -->  
    </div>  
  </div>  
</div> 


<style>
.center-container.is-table { 
    display: table; 
}  
.is-table .table-cell {  
  display: table-cell;  
  vertical-align: middle;   // 這時,直接使用 vertical-align 即可  
}  
.is-table .center-block {  
  width: 50%;  
  margin: 0 auto;  
} 

</style>

優點:

1)高度可變
2)內容溢出會將父元素撐開。
3)跨瀏覽器兼容性好。

缺點:需要額外html標記

四、行內塊元素(Inline-Block)

這是一種很受歡迎的實現方式,基本思想是使用display: inline-block, vertical-align: middle和一個偽元素讓內容塊處於容器中央。這個概念的解釋可以參考CSS-Tricks上的文章《Centering in the Unknown》

如果內容塊寬度大於容器寬度,比如放了一個很長的文本,但內容塊寬度設置最大不能超過容器的100%減去0.25em,否則使用偽元素:after內容塊會被擠到容器頂部,使用:before內容塊會向下偏移100%。

如果你的內容塊需要占據盡可能多的水平空間,可以使用max-width: 99%;(針對較大的容器)或max-width: calc(100% -0.25em)(取決於支持的瀏覽器和容器寬度)。

<!-- HTML -->
<div class="Center-Container is-Inline">  
  <div class="Center-Block">  
    <!-- CONTENT -->  
  </div>  
</div>  


<style>
.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+ */   
}  
</style>

這種方法的優劣和單元格Table-Cell方式差不多,起初我把這種方式忽略掉了,因為這確實是一種hack方法。不過,無論如何,這是很流行的一種用法,瀏覽器支持的也很好。

優點:

1)高度可變
2)內容溢出會將父元素撐開。
3)支持跨瀏覽器,也適應於IE7。

缺點:

1)需要一個容器
2)水平居中依賴於margin-left: -0.25em;該尺寸對於不同的字體/字號需要調整。
3)內容塊寬度不能超過容器的100% - 0.25em。

五、Flexbox

這是CSS布局未來的趨勢。Flexbox是css3新增屬性,設計初衷是為了解決像垂直居中這樣的常見布局問題。相關的文章如《Centering Elements with Flexbox》

記住Flexbox不只是用於居中,也可以分欄或者解決一些令人抓狂的布局問題。

優點:

1)內容塊的寬高任意,優雅的溢出。
2)可用於更復雜高級的布局技術中。

缺點:

1)IE8/IE9不支持。
2)Body需要特定的容器和CSS樣式。
3)運行於現代瀏覽器上的代碼需要瀏覽器廠商前綴。
4)表現上可能會有一些問題

有關Flexbox Centering的文章可以參考David Storey的文章《Designing CSS Layouts WithFlexbox Is As Easy As Pie》

建議:

每種技術都有其優劣之處。你選擇哪一種技術取決於支持的瀏覽器和你的編碼。使用上面的對照表有助於你做出決定。

作為一種簡單的替代方案,絕對居中(Absolute Centering)技術表現良好。曾經你使用負邊距(Negative Margins)的地方,現在可以用絕對居中(Absolute Centering)替代了。你不再需要處理討厭的邊距計算和額外的標記,而且還能讓內容塊自適應大小居中。

如果你的站點需要可變高度的內容,可以試試單元格(Table-Cell)和行內塊元素(Inline-Block)這兩種方法。如果你處在流血的邊緣,試試Flexbox,體驗一下這一高級布局技術的好處吧。


Refer: 盤點8種CSS實現垂直居中水平居中的絕對定位居中技術


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: