標籤:des blog http io ar os 使用 sp for
問題情境
應用的地方比較普遍,這裡有兩個赤裸裸的栗子:
也有很多流行的方案,這裡只針對各種方案的適用情境來做一些分析
問題抽象
其實,垂直置中問題可以簡化成這樣:一個容器HTML元素(#container),一個需要置中的HTML元素(#center)。特殊的情形下可能會出現body為#container,#center是圖片,此處不予討論。 #center 可能有高度,也可能沒有,也可能是響應式的。總之,代碼的結構如所示:
再有就是瀏覽器的相容性問題:IE6,IE7.....不說了,都是淚。總之,我們要做的就是在相應的代碼處填入代碼以期達到目的。:
方案一:負外邊距(Negative Margins)
這種方案應該是最流行的,思路也比較簡單,瀏覽器的相容性(IE6+)也比較好,但是必須要指定#center的高度,也無法進行響應式處理(類似height:60%,max-width:400px;)
如果能確定#center高度,並且無需響應式,這種方案是最棒的!
方案二:絕對位置置中(Absolute Centering)
該方法相容IE8+,雖然可以自適應,雖然padding可以不用操心,但是還是必須聲明高度!關於這種方案的工作原理:
- 在普通內容流(normal content flow)中,margin:auto的效果等同於margin-top:0;margin-bottom:0。
- position:absolute使絕對位置塊跳出了內容流,內容流中的其餘部分渲染時絕對位置部分不進行渲染。
- 為塊地區設定top: 0; left: 0; bottom: 0; right: 0;將給瀏覽器重新分配一個邊界框,此時該塊block將填充其父元素的所有可用空間,父元素一般為body或者聲明為position:relative;的容器。
- 給內容塊設定一個高度height或寬度width,能夠防止內容塊佔據所有的可用空間,促使瀏覽器根據新的邊界框重新計算margin:auto
- 由於內容塊被絕對位置,脫離了正常的內容流,瀏覽器會給margin-top,margin-bottom相同的值,使元素塊在先前定義的邊界內置中。
- 總之:絕對位置元素不在普通內容流中渲染,因此margin:auto可以使內容在通過top: 0; left: 0; bottom: 0;right: 0;設定的邊界內垂直置中。
方案三:變形(Transforms)
這種方案是方案一的一種延伸,它解決了方案一必須指定高度,不支援響應式的問題,但是瀏覽器安全色性不佳,只支援IE9+,但是在移動版的瀏覽器卻可以放心的使用哦!
另外,這種方案可能需要在transform上加入首碼,不過如果有less和sass這樣的東西就好多了,瞬間,又有了對IE的鄙視!
方案四:表格儲存格(table-cell)
思路是這樣的: <table><tr><td>I am Centered</td></tr></table>
,代碼是這樣的:
- 1.需要木有語義的多餘的標籤嵌套
- 2.相容IE8+
- 3.可能在一些瀏覽器上有問題(特別是IE)
由於相容上的一些問題,這個方案,不太建議。
方案五:行內塊元素(inline-block)
思路為:期望在#container中:text-align:center;
,在#center中:vertical-align:middle;
達到目的,但是#center卻無法撐開#container,咋辦呢? 可以在#container裡面加入一個多餘的display為inline-block的div(作為#container的一個child),將#container的高度撐開,就像這樣:
如果支援:before或者:after的瀏覽器,就可以高大山一些:
但是,還存在如下兩個問題:
- 由於兩個inline-block的元素之間預設是有間隙的,所以需要在#center中margin-right為負值或者在#container中font-size:0px;(如果#center為圖片的情況下)進行調整
- #center的寬度不能大於#container的100%-間隙,否則before將會被擠走
方案六:Flexbox
這個應該是最簡單的,如下:
原理為:margin:auto;自動擷取伸縮容器中剩餘的空間,設定垂直方向margin值為auto,可以使伸縮項目在伸縮容器的兩上軸方向都完全集中。我覺得,實際上相當於這樣:
關於Flexbox,請參見 這裡
但是flex的缺點也是顯而易見的,不支援老舊的瀏覽器。
總結
以上各種方案,各有優缺,希望大家趕緊提建議,我也將能夠通用的代碼全部整到了github上(這裡)
參考
- http://www.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/
- http://www.w3cplus.com/css3/a-guide-to-flexbox.html
- http://www.smashingmagazine.com/2013/05/22/centering-elements-with-flexbox/
- http://www.zhangxinxu.com/wordpress/2010/10/%E6%88%91%E6%89%80%E7%9F%A5%E9%81%93%E7%9A%84%E5%87%A0%E7%A7%8Ddisplaytable-cell%E7%9A%84%E5%BA%94%E7%94%A8/
- http://www.zhangxinxu.com/wordpress/2013/11/margin-auto-absolute-%E7%BB%9D%E5%AF%B9%E5%AE%9A%E4%BD%8D-%E6%B0%B4%E5%B9%B3%E5%9E%82%E7%9B%B4%E5%B1%85%E4%B8%AD/
- http://www.zhangxinxu.com/wordpress/2009/08/大小不固定的圖片、多行文字的水平垂直置中
- http://designshack.net/articles/css/how-to-center-anything-with-css
- http://css-tricks.com/centering-in-the-unknown/
- https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform
CSS垂直置中解決方案