css布局 - 垂直居中布局的一百種實現方式(更新中...)
首先將垂直居中的現象和實現方式兩大方向細分類如下:
接下來逐條累加不同情況下的垂直居中實現。
目錄:
一、父元素高度固定時,單行文本 | 圖片的垂直居中
1. line-height行高簡單粗暴實現法:line-height:Npx(N = 與元素高度相同的值)
2. vertical-middle上場:
二、父元素高度固定時,多行文本的垂直居中
1. 幫多行文本找一個繼父來領養他,讓繼父彌補父元素給他帶來的傷害(行高和水平居中對齊的樣式修改)
2. margin負邊距簡單處理一下底部小“裂痕”
三、父元素高度 不 固定時,單行文本 | 圖片的絕對垂直居中
1. 新增兄弟節點實力輔助,目標元素輕松上王者
四、父元素高度 不 固定時,多行文本的絕對垂直居中
1. 新增兄弟節點實力輔助,目標元素輕松上王者
五、目標元素寬高固定時,元素的水平垂直居中(經典彈層布局有寬高)
1. absolute定位飄起來
2. 上左50%方位值,先讓左上角處於視圖中心點
3. margin負邊距,再讓身子中心點挪到視圖中心點
六、目標元素寬高也不固定時,元素依然水平垂直居中(經典彈層布局無寬高)
1. absolute定位飄起來
2. 上左50%方位值,先讓左上角處於視圖中心點
3. translate -50%偏移,實現自動化偏移相應數值到中心點
七、圖片和多行文本的 兩列垂直居中(經典布局難題)
1. 兩端對齊交給爹地
2. 兄弟齊心,vertical-align: middle;實現居中布局
八、堪稱萬能鑰匙的公共垂直居中解法。無視父元素高度是否固定!無視文字多少行!
(一)靈魂輔助的vertical-align:middle值
(二)擁有家世淵源的table來救場
(三)帶著尚方寶劍的display: table-cell
(四)小機靈鬼兒translate對應方向上的-50%
(五)flex大大一句話 水平垂直全拿下
正文
一、最簡單的,父元素高度固定的單行文本(或單個圖片)垂直居中
實現方式:
1、line-height行高簡單粗暴實現法: line-height:Npx(N = 與元素高度相同的值)
正如N的值那樣,這種解決方法就是要盒模型是有高度設置的。舉例:
假如設計稿元素高度是300px,行高就設置為300px,這樣,就可以實現垂直居中的問題。
.box1{ text-align: center; line-height: 300px; }
如圖: 影視二字就可以垂直居中了。
可行性分析:就像圖片中看到的那樣,只有兩個字,他們排在一行不會換行。所以實際應用中要確保一定是單行文本不會換行。因為一旦換行的話,行高就會應用於文字,由於行高過大的原因,會導致剩下的文字跑出畫面了。
如右圖: 這種情況也可以使用overflow:hidden;做一下保障措施。不過治標不治本。
另外補充一點:
有人看到這個現象可能會想是因為line-height導致的,那我給文字包裹一個框比如span,然後給span文字元素單獨設置一個正常的行高不久可以了嗎?
真的可以了嗎?
看圖:
中間文字部分就是span包裹的,並設置如下:
.box1 { text-align: center; line-height: 300px; } .span1 { line-height: 21px; display: inline-block; }
結果怎麽樣呢?
不僅文字和行數少一點的時候,不能完全的垂直居中。甚至文字再多會有這樣的現象:
可見這種假設不合理。
所以單獨設置一個行高就解決垂直居中問題看似大快人心,但是代碼很不健壯,只局限於特別個別的情況。經不起考驗。
那好,現在我直接使用這個方法實現一個寬高固定的圖片垂直居中應該也很贊了吧?!
結果一頓操作這個結果我很不滿意:
這不用比較也知道,我的圖片沒有上下垂直居中啊!毛線。那個標題還那麽深,實例打臉。
但究竟是因為什麽呢?我往圖片後邊寫了一個x輔助理解,這下明白了吧!圖片默認是文本基線對其的。文本垂直居中,就到垂直正中間那裏。但是圖片底部為了與文字底部對其,所以留給頂部的空間就不多了。沒有x的時候會有一個空白的換行節點在搗鬼,這也是為什麽單獨文字的時候看不出毛病,單獨圖片使用同樣的方法卻有問題的原因。
啊,這就是聽張鑫旭老師講課的收獲!
接下來,要實現單個圖片的垂直居中效果我只需要讓圖片和文字水平一條線垂直對其就可以了。
2. vertical-middle上場:
.box1 { text-align: center; line-height: 300px; } img { vertical-align: middle; }
line-height配合vertical-align,搞定。
但是真的要1像素走查的時候,你又會發現,這種做法還是不能完全完全的垂直居中,底部還是差那麽一兩像素。這個問題接下來再說。
二、父元素高度固定的多行文本垂直居中
這種效果其實和中間只有一個圖片一個道理,因為你需要幫多行文本找一個繼父來領養他,所以結構上就是這樣:
1 <div class="content-box"> 2 <div class="content">我是多行文本。多行文本水平垂直居中的原理跟上一頁圖片的實現是一樣的,區別在於要把多行文本所在的容器的display水平轉換成和圖片一樣的,也就是inline-block,以及重置外部繼承的text-align和line-height屬性值。</div> 3 </div>
中間content這個元素就好比一個圖片,要實現他的水平垂直居中,那麽他就得變成一個inline-block元素,(圖片本身就是inline-block所以在上一段才沒有強調。)
.content-box { line-height: 300px; text-align: center; } .content { width: 500px; display: inline-block; vertical-align: middle; }
不出乎意料的這裏出現了上邊兩個出現過的問題:
1.因為父元素行高的原因,content內部行高過高導致文字行距過大:
所以content內部就要單獨設置行高以覆蓋繼承自父元素的值:ling-height:21px;(一般改為比字體大小大個4、5像素即可。)
2. 因為父元素要對inline-block的子元素content實行text-align:center;限制,導致content內部的文字都居中了,
所以需要text-align:left;糾正。
哇,我驚喜的發現,現在文字行數增多或減少,好像真的看上去垂直居中了哎!
等等,高興的太早,又發現和單個圖片垂直居中的相同問題,頂部和底部預留的空間好像不一般多啊!
紅框是我加的before、after等偽類,以顯示的讓我們看到上下的剩余空間相差多少。
這一點真的和之前的圖片問題很接近:
我把兩個例子的代碼挪到一個html頁面,驚奇的發現,底部剩余空間都是比頂部少4像素!
於是,一不做二不休,我直接使用margin負值讓元素再之前的基礎上向上4像素,竟真的實現了絕對的垂直居中。
總結:要想絕對的垂直居中,有了上邊的核心代碼設置外,還要加一個margin-top: -4px;就可以啦!
不過具體情況具體分析,換個頁面,字體大小不一樣,對行高的影響也不一樣,自然偏差也不一定是4像素,新的負數值再重新計算即可。
總結關鍵點:
1、父子齊心,line-height斷難題。
2、鼎鼎大名,margin負邊距。
可行性分析:這種再根據當前頁或當前元素字體大小調整margin負邊距大小值的做法實屬有點不妥。
不過還好最近跟大神學了一招“萬能膠”。這裏暫且按下不表。請看下文如何不動聲色且完美的解決這偏差的幾像素。
三、父元素高度不固定,單行文本居中
既然父元素高度不固定,那肯定就沒有line-height秀的機會了。
(特別說明,第三條系列中的父元素height值只是為了撐開然後填充背景色看的。高度不確定不代表沒有高度,所以這裏是高度值隨意改變,內部子元素永遠垂直居中的獨秀專場)。
那我們派誰打頭陣呢?只見父元素瞇眼一想,span,讓你的vertical-align出來表演一下吧!我再給你生個小弟弟你們一起秀!
1. 單個圖片的絕對垂直居中
不賣關子,直接上代碼和解釋:
<div class="box"> <img src="https://img1.mukewang.com/user/57a6f85b00013c7202090209-100-100.jpg" alt=""> <span class="assist"></span> </div>
.box { height: 200px; text-align: center; background: #f5f5f5; border: 1px solid #eee; } img { /* 第一步,元素inline-block化,因為圖片本身是所以省去。 */ /* display:inline-block; */ /* 第三步,圖片和輔助元素同時垂直居中對齊 */ vertical-align: middle; } span.assist { /* 第二步,0寬度100%高度的輔助元素 */ display: inline-block; height: 100%; /* 第三步,圖片和輔助元素同時垂直居中對齊 */ vertical-align: middle; }
所謂三步走策略,這裏偷懶把註釋都寫進代碼裏了。越是經典的解決方法越是直接背誦就好了。我就不喋喋不休分散看官的註意力了。
再不懂的去慕課網聽張老師的課程。鏈接(3分27秒左右):https://www.imooc.com/video/10407。
2. 單行文本的絕對垂直居中
1 <div class="box box2"> 2 <span class="txts"> 3 大小不固定的文字垂直居中 4 <br> 5 多行文本也可以哦! 6 </span> 7 <i></i> 8 </div>
.box2 span.txts { /* inline-block化,形成塊狀整體才適用垂直居中。 */ display: inline-block; vertical-align: middle; } .box2 i { display: inline-block; height: 100%; vertical-align: middle; }
這裏css有偷懶,只是針對文本的設置,其他普通公用設置見上邊第1條單個圖片絕對垂直居中那裏。
四、父元素高度不固定,多行文本居中
還是給文本生個小弟弟陪他玩耍:
-
主體元素inline-block化
-
0寬度100%高度輔助元素
-
vertical-align:middle
見第三條第二點。同理,單行文本換成多行即可。。。
五、目標元素寬高固定的水平垂直居中(經典彈層布局)
這個很常見了,就不多說什麽了:
直接上代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="author" content="guojufeng@ xing.org1^"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>寬高確定的正經彈層</title> <style> .mask{ position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0,0,0,.5); } .layer{ width: 300px; height: 300px; position: absolute; top: 50%; left: 50%; /* margin: -150px auto auto -150px; */ margin-top: -150px; margin-left: -150px; text-align: center; background: #fff; border-radius: 8px; } span{ padding: 100px; display: inline-block; } </style> </head> <body> <h1>我是body裏的內容,哦吼吼!xing.org1^</h1> <!-- 蒙層 --> <div class="mask"> <!-- 彈層 - 垂直居中實現 --> <div class="layer xingorg1"> <span>我是寬高固定的彈層元素,我實現了垂直居中。</span> </div> </div> </body> </html>
六、目標元素寬高也不固定的水平垂直居中(經典彈層布局)
這次重點說說來救場的transform:translate(負值%);
css3中,translate就是指定元素像對應方向偏移,x是水平偏移,y是垂直方向的偏移,因為這篇是方法匯總,不做過多介紹,請自行查看w3c或實驗。也看移駕這篇文章:https://www.cnblogs.com/padding1015/p/9550142.html
不過他又一個屌炸天的特性是,當偏移數值的單位為百分比的時候,會相對於本身的長寬來計算偏移值。比如元素的寬度是300px的時候,我們都知道想要讓他再向左移動50%寬度,配合上left:50%;就能實現居中。
剛好,translateX(-50%)自動計算得到的就是50%寬度的值。所以,我們不需要知道目標元素的寬高也一樣能實現居中了。
對於這一特性,這個慕課網問答這裏講的很好:http://www.imooc.com/qadetail/129282
他除了適用於這個彈層的場景,同樣適用於其他場景的居中。因為即使不浮動,translate移動對兄弟元素沒有影響。
請看:
這種現象和margin移動不一樣。只不過其他場景使用translate有點大材小用。
關鍵點分析:
利用transform來實現垂直居中布局:
box盒使用固定寬度的width+margin auto,實現水平居中。
position:relative,top: 50%;實現垂直方向的偏移。
因為沒有高度固定,所以無法確切的使用margin-top負值實現垂直居中
但是css3中的transform的translate屬性,會自動根據盒子高度計算偏移值。
所以:position:relative; + top: 50%; + transform:translateY(-50%);可以實現垂直方向的絕對居中效果。
如果將relative換成absolute,想實現水平垂直居中的彈窗效果時:
因為固定寬度,可以使用margin負值,即margin-left: -300px;實現水平布局。
但是,學習就要舉一反三,我們同樣可以
利用transform來實現水平居中布局:
position: absolute;
left: 50%;
transform: translateX(-50%);
一樣可以實現!
那麽,如果跟之前的垂直居中合並起來的話,transform是不是也可以寫一條呢?
transform: translate(-50%,-50%);
好了,廢話說的再多也不如貼源碼運行一探究竟:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="author" content="guojufeng@ xing.org1^"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>translateY實現垂直居中</title> <style> html, body, ul { height: 100%; margin: 0; } .mask { position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0, 0, 0, .5); } .layer { position: absolute; top: 50%; left: 50%; /* transform: translateX(-50%) translateY(-50%); 這種寫法也可以,相當於寫兩個translate*/ transform: translate(-50%,-50%); text-align: center; background: #fff; border-radius: 8px; } .box { /* width: 500px;*/ /* height: 350px; */ padding: 30px 10px; background: rgba(255, 51, 255, 0.2901960784313726); } </style> </head> <body> <h1>我是body裏的內容,哦吼吼!xing.org1^</h1> <h1>translate負值實現元素的水平垂直居中</h1> <!-- 蒙層 --> <div class="mask"> <!-- 彈層 - 垂直居中實現 --> <div class="layer xingorg1"> <div class="box"> <ul> <li>關鍵點</li> <li>left: 0; right: 0; bottom: 0; margin: auto;</li> <li>top: 50%;</li> <li>transform: translateY(-50%);</li> <li>這些li是為了撐開box的高度</li> </ul> </div> </div> </div> </body> </html>
七、圖片和多行文本兩列的垂直居中(經典布局難題)
1、兄弟們一起 vertical-align:middle;
先看誘惑人的結果,就是不管文字單行還是多行,不管圖片改成多大,都能實現的效果:
然後再說解決方法。核心就是用了 vertical-align:middle;
html結構:
<div class="box"> <span>單行文字</span> <img src="https://img1.mukewang.com/user/57a6f85b00013c7202090209-40-40.jpg" alt=""> </div> <div class="box"> <span>多行文字<br />文字文字文字文字<br />文字文字文字文字</span> <img src="https://img1.mukewang.com/user/57a6f85b00013c7202090209-40-40.jpg" alt=""> </div> <div class="box"> <span>因為vertical-align只對inline/inline-block元素起作用,而浮動會讓元素block水平化,就不能使用vertical-align對齊了</span> <img src="https://img1.mukewang.com/user/57a6f85b00013c7202090209-40-40.jpg" alt=""> </div>
關鍵點1:外邊的box實現兩端對齊
因為vertical-align只對inline/inline-block元素起作用,而浮動會讓元素block水平化,就不能使用vertical-align對齊了。
所以這裏才用 text-align: justify; 附加給父元素,實現圖文的兩端對齊效果
關鍵點2:文本span元素
vertical-align: middle;
這裏文本因為需要有個寬度值限制,所以inline-block化了,要知道,不是必須即可。
關鍵點3:img元素
vertical-align: middle;
八、堪稱萬能鑰匙的公共垂直居中解法。無視父元素高度是否固定!無視文字多少行!
(一)靈魂輔助的vertical-align:middle值
具體見上邊第三條的例子,用一個span空標簽放到需要垂直居中元素的後邊或者前邊,作為輔助兄弟元素。
同時給這個輔助元素和目標元素vertical-align:middle; display:inline-block;一頓操作即可。
css 中有一個用於豎直居中的屬性 vertical-align,在父元素設置此樣式時,會對inline-block類型的子元素都有用。
(二)擁有家世淵源的table來救場
就像上例中輔助元素的vertical-align原理一樣,td 標簽默認情況下就默認設置了 vertical-align 為 middle,所以我們不需要顯式地設置,使用table布局就可以完成完美的自動水平垂直居中了。
但是這種布局方式畢竟拘束,在實現垂直居中後,還需要一大堆的代碼把tabel的樣子抹掉。
所以知道有這種方法,平時根本不用也沒必要用,我也不去實踐了。
(三)帶著尚方寶劍的display: table-cell
即,設置塊級元素的 display 為 table-cell。
之所以說display:table-cell; 是帶著尚方寶劍的,是因為這麽做就相當於設置為表格單元顯示。
但這種方法兼容性比較差,只是提供大家學習參考。
在 chrome、firefox 及 IE8 以上的瀏覽器下可以設置塊級元素的 display 為 table-cell(設置為表格單元顯示),激活 vertical-align 屬性,
註意 IE6、7 並不支持這個樣式, 兼容性比較差。
<div class="container"> <div> <p>看我是否可以居中。</p> <p>看我是否可以居中。</p> <p>看我是否可以居中。</p> </div> </div>
<style> .container { height:300px; background:#ccc; display:table-cell; /*IE8以上及Chrome、Firefox*/ vertical-align:middle; /*IE8以上及Chrome、Firefox*/ } </style>
這種方法的好處是不用添加多余的無意義的標簽,但缺點也很明顯,它的兼容性不是很好,不兼容 IE6、7而且這樣修改display的block變成了table-cell,破壞了原有的塊狀元素的性質。
(四)小機靈鬼兒translate對應方向上的-50%
具體原理和使用方法及案例見上邊。不再贅述。
(五)flex大大一句話 水平垂直全拿下
這個相信不用我說,大家一看就明白怎麽回事了。
Flex彈性盒布局屬性,此系列中還有兩個屬性justify-content 和 align-items 分別用於實現水平居中和垂直居中。
具體flex的學習可以參考這兩篇:
Flex 布局教程:語法篇 作者: 阮一峰
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
Flex 布局教程:實例篇作者: 阮一峰
http://www.ruanyifeng.com/blog/2015/07/flex-examples.html
簡易的代碼見下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="author" content="guojufeng@ xing.org1^"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>萬能方法</title> </head> <body> <div class="flex xingorg1"> <span>前端小學生~ _xing.org1^</span> </div> <div class="flex xingorg1"> <span>不會搞藝術的程序員不是好的設計師 _xing.org1^ 不會搞藝術的程序員不是好的設計師 _xing.org1^ </span> </div> <style> .flex{ margin-bottom: 10px; padding: 20px; width: 300px; height: 300px; background: #f5f5f5; border: 1px solid #eee; /* flex寫法 */ display: flex; justify-content: center; align-items: center; } </style> </body> </html>
雖說古老的ie不支持這種布局,但是寫上hack後,用在移動端的項目中簡直完美啊。
小程序不就默認這麽寫的麽。
2018-09-11 12:42:49
聲明:
請尊重博客園原創精神,轉載或使用圖片請註明:
博主:xing.org1^
出處:http://www.cnblogs.com/padding1015/
css布局 - 垂直居中布局的一百種實現方式(更新中...)