"44年前咱們就把人類送上了月球了,但如今咱們仍然沒法在css中實現垂直居中 -James Anderson"css
在CSS中對元素進行水平居中是很是簡單的;若是是一個行內元素,就對父元素設置text-align:center;若是是一個它是一個塊級元素,就對自身應用margin:auto.然而考慮到代碼的DRY和較強的可維護性,若是要對一個元素進行垂直居中,多是使人頭皮發麻的一件事情了.html
就這樣在前端開發圈內看似及其常見的需求,從理論上彷佛極其簡單,在實踐中,它每每難如登天,當涉及尺寸不固定的元素時尤其如此.前端
爲了解決這一"絕世難題",因而前端開發者們殫精竭慮,腦洞大開,琢磨出了各類解決方案,大多數並不實用.web
一路走來走了很多彎路,但願初入前端的小夥伴們能夠走的更加通暢,總結分享給你們:瀏覽器
下面就讓咱們來探索現代css的強大威力:編輯器
利用表格的顯示模式,須要用到一些冗餘的HTML元素函數
思路來源:佈局
<table style="width:100%;height:100%;"> <tr> <td style="text-align: center; vertical-align: middle;"> Unknown stuff to be centered. </td> </tr> </table>
html,body{ height:100%; }
摘自:https://css-tricks.com/centering-in-the-unknown/flex
咱們發如今table中vertical-align: middle;實現了自動垂直居中.flexbox
See the Pen css-table-verticalMiddle by okaychen (@okaychen) on CodePen.
基於曾經在網頁早期風靡一時的表格佈局法:實現了垂直居中
可是因爲表格佈局法逐漸的退出舞臺,這種方法也漸漸的不爲所用
早期實現垂直居中方法,要求具備固定的寬度和高度:
main{ position:absolute; top:50%; left:50%; magin-top:-3em; margin-left:-9em; width:18em; height:6em; }
這種方法利用負外邊距移動的方法,從而把元素放在視口的正中心.咱們還能夠藉助強大的calc
函數,省掉兩行聲明:
main{ position:absolute; top:calc(50%-3em); left:calc(50%-9em); width:18em; height:6em; }
顯然這個方法最大的侷限性就是他要求元素具備固定寬度和高度.咱們知道在一般狀況下,固定寬度和高度的狀況是極少的,對於那些須要居中的元素來講,其尺寸每每是由其內容決定的.若是可以找到一個屬性的百分比以元素自身的寬高做爲基準,那麼難題就迎刃而解!遺憾的是,對於大多數的css屬性(包括margin)來講,百分比都是以其父元素的尺寸爲基準進行解析的
css領域有一個很常見的現象,真正的解決方案每每來自咱們最意想不到的地方:利用css變形屬性,
當咱們在進行
translate()
變形函數中使用百分比值時,是以這個元素位基準進行轉換和移動的
,而這正是咱們所須要的.
main{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); }
See the Pen css-lineCenter-position by okaychen (@okaychen) on CodePen.
從codepen中看到,利用css變形技巧,這個容器已經完美居中,知足咱們的指望.
可是沒有任何技巧十全十美,咱們須要注意幾點:
咱們有時不能選擇絕對定位,他對整個佈局影響太過強烈
若是須要居中的元素已經在高度上超過了視口,那它的頂部部分就會被視口裁掉
在某些瀏覽器中,這個方法可能會致使元素的顯示模糊,由於元素可能會被放置在半個元素上.能夠用一個偏hack的手段來修復transform-style:preserve-3d
假設咱們不使用絕對定位,仍然採用translate()
技巧來把這個元素以其自身寬高的一半爲距離進行移動;可是在缺乏left和top的狀況下,如何吧這個元素放在容器正中心呢?
咱們的第一反應極可能用margin屬性的百分比值來實現,就像這樣:
main{ width:18em; padding:1em 1.5em; margin:50% auto 0; transform:translateY(-50%); }
可是卻產生了十分離譜的效果.緣由在於margin的百分比值是以父元素的寬度做爲解析基準的
在CSS值與單位(第三版)定義了一套新的單位,稱爲視口相關的長度單位
vm是與視口寬度相關的.1vm至關於視口的1%
與vw相似,1vh至關於視口的1%
當視口寬度小於高度時,1vmin等於1vw,不然等於1vh
當視口寬度大於高度時,1vmax等於1vw,不然等於1vh
在這個例子中,咱們適用外邊距的是vh單位
main{ width:18em; padding:1em 1.5em; magin:50vh auto 0; transform:translateY(-50%); }
See the Pen css-lineCenter-vm by okaychen (@okaychen) on CodePen.
咱們能夠看到,其效果堪稱完美.這個技巧更適合於在視口中居中的場景.
這是毋庸置疑的最佳解決方案,由於Flexbox(伸縮盒)是專門針對這類需求所設計的.現代瀏覽器對於Flexbox支持度已經至關不錯了
咱們只須要兩行聲明便可:先給這個待定居中元素的父元素設置display:flex
(在使用的例子中是body元素),在給這個元素設置咱們在熟悉不過的margin:auto
body{ display:flex; min-height:100vh; margin:0; } main{ margin:auto; }
Flexbox還有一個好處就是,它能夠將匿名容器(即便沒有節點包裹的文本節點)垂直居中.
<main>center me,place!</main>
藉助Flexbox規範所吸引人的align-items
和justify-content
屬性,咱們可讓它內部文本也實現居中
main{ display:flex; align-items:center; justify-content:center; width:18em; height:10em; }
根據盒對齊模型(第三版)的計劃,在將來,對於簡單的垂直居中的要求,咱們徹底不須要動用特殊的佈局模式.咱們只須要這行代碼就能夠搞定
align-self:center;
不知不覺間,咱們身邊的瀏覽器都開始讓它成爲現實(可是路途還很遙遠:IE10及更早版本不支持,Safari 7.0 及更早版本使用-webkit前綴)
由於使用博客園的Markdown編輯器,codepen部分沒法顯示,建議跳到個人博客- -;
原文地址:http://www.chenqaq.com/2017/12/07/css-verticalMiddle/
參考資料
《CSS Secrets 》
CSS-tricks:https://css-tricks.com/centering-in-the-unknown/
CSS變形:http://w3.org/TR/css-transforms
CSS值與單位:http://w3.org/TR/css-values
CSS伸縮盒佈局模型:http://w3.org/TR/css-flexbox
CSS盒對齊模型:http://w3.org/TR/css-align