css佈局 - 垂直居中佈局的一百種實現方式(更新中...)

首先將垂直居中的現象和實現方式兩大方向細分類以下:

 

接下來逐條累加不一樣狀況下的垂直居中實現。css

目錄:

1、父元素高度固定時,單行文本 | 圖片的垂直居中

1. line-height行高簡單粗暴實現法:line-height:Npx(N = 與元素高度相同的值)html

2.  vertical-middle上場:前端

2、父元素高度固定時,多行文本的垂直居中

1. 幫多行文本找一個繼父來領養他,讓繼父彌補父元素給他帶來的傷害(行高和水平居中對齊的樣式修改)css3

2. margin負邊距簡單處理一下底部小「裂痕」程序員

3、父元素高度 不 固定時,單行文本 | 圖片的絕對垂直居中

1. 新增兄弟節點實力輔助,目標元素輕鬆上王者chrome

4、父元素高度 不 固定時,多行文本的絕對垂直居中

1. 新增兄弟節點實力輔助,目標元素輕鬆上王者小程序

5、 目標元素寬高固定時,元素的水平垂直居中(經典彈層佈局有寬高)

 1. absolute定位飄起來瀏覽器

 2. 上左50%方位值,先讓左上角處於視圖中心點ide

 3. margin負邊距,再讓身子中心點挪到視圖中心點佈局

 4. calc自動計算實現

6、目標元素寬高也不固定時,元素依然水平垂直居中(經典彈層佈局無寬高)

 1. absolute定位飄起來

 2. 上左50%方位值,先讓左上角處於視圖中心點

 3. translate -50%偏移,實現自動化偏移相應數值到中心點

 

【很是】 六加1、寬高可定可不定的全屏垂直居中效果

 

7、圖片和多行文本的 兩列垂直居中(經典佈局難題)

1. 兩端對齊交給爹地

2. 兄弟齊心,vertical-align: middle;實現居中佈局

8、堪稱萬能鑰匙的公共垂直居中解法。無視父元素高度是否固定!無視文字多少行!

(一)靈魂輔助的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字符的底部絕對是對齊的!!這下明白了吧!圖片默認是文本基線對其的。文本垂直居中,就到垂直正中間那裏。可是圖片底部爲了與文字底部對其,因此留給頂部的空間就很少了。沒有x的時候會有一個空白的換行節點在搗鬼,這也是爲何單獨文字的時候看不出毛病,單獨圖片使用一樣的方法卻有問題的緣由。

 

啊,這就是聽張鑫旭老師講課的收穫!

接下來,要實現單個圖片的垂直居中效果我只須要讓圖片和文字水平一條線垂直對其就能夠了。

2. vertical-middle上場:

.box1 {
    text-align: center;
    line-height: 300px;
}
img {
    vertical-align: middle;
}

line-height配合vertical-align,搞定。

可是真的要1像素走查的時候,你又會發現,這種作法仍是不能徹底徹底的垂直居中,底部仍是差那麼一兩像素。這個問題接下來再說。

 

2、父元素高度固定的多行文本垂直居中

這種效果其實和中間只有一個圖片一個道理,由於你須要幫多行文本找一個繼父來領養他,因此結構上就是這樣:

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;(通常改成比字體大小大個四、5像素便可。)

 

2. 由於父元素要對inline-block的子元素content實行text-align:center;限制,致使content內部的文字都居中了,

因此須要text-align:left;糾正。

哇,我驚喜的發現,如今文字行數增多或減小,好像真的看上去垂直居中了哎!

 

 

等等,高興的太早,又發現和單個圖片垂直居中的相同問題,頂部和底部預留的空間好像不通常多啊!

 

紅框是我加的before、after等僞類,以顯示的讓咱們看到上下的剩餘空間相差多少。

這一點真的和以前的圖片問題很接近:

 

 

我把兩個例子的代碼挪到一個html頁面,驚奇的發現,底部剩餘空間都是比頂部少4像素!

因而,一不作二不休,我直接使用margin負值讓元素再以前的基礎上向上4像素,竟真的實現了絕對的垂直居中。

 

 

總結:要想絕對的垂直居中,有了上邊的核心代碼設置外,還要加一個margin-top: -4px;就能夠啦!

不過具體狀況具體分析,換個頁面,字體大小不同,對行高的影響也不同,天然誤差也不必定是4像素,新的負數值再從新計算便可。

 

總結關鍵點:

一、父子齊心,line-height斷難題。

二、鼎鼎大名,margin負邊距。

可行性分析:這種再根據當前頁或當前元素字體大小調整margin負邊距大小值的作法實屬有點不妥。

不過還好最近跟大神學了一招「萬能膠」。這裏暫且按下不表。請看下文如何不動聲色且完美的解決這誤差的幾像素。

3、父元素高度不固定,單行文本居中

既然父元素高度不固定,那確定就沒有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條單個圖片絕對垂直居中那裏。

 

 

4、父元素高度不固定,多行文本居中

 

 仍是給文本生個小弟弟陪他玩耍:

 

  1. 主體元素inline-block化

  2. 0寬度100%高度輔助元素

  3. vertical-align:middle

 

見第三條第二點。同理,單行文本換成多行便可。。

 

 

5、目標元素寬高固定的水平垂直居中(經典彈層佈局)

 

這個很常見了,就很少說什麼了:

直接上代碼:

 

<!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>

2019-03-03  15:41:55  補calc寫法實現:

div{
  width: 100px;
  height: 100px;
  background: #000;
  position: absolute;
  left: calc(50% - 50px);
  top: calc(50% - 50px);
}

  

 

6、目標元素寬高也不固定的水平垂直居中(經典彈層佈局)

 

此次重點說說來救場的transform:translate(負值%);

css3中,translate就是指定元素像對應方向偏移,x是水平偏移,y是垂直方向的偏移,由於這篇是方法彙總,不作過多介紹,請自行查看w3c或實驗。也看移駕這篇文章:http://www.javashuo.com/article/p-vxemvgjy-kc.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負值實現垂直居中

可是translateY屬性,會自動根據盒子高度計算偏移值。translateY(-50%)就會向上偏移50%的高度值。因此:

position:relative(或者absolute);  +  top: 50%;  +  transform:translateY(-50%);能夠實現垂直方向的絕對居中效果。

 

可是,學習就要觸類旁通,咱們一樣能夠

利用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>

可是,bug來的太忽然、、、2018-09-26 10:29:06 

上邊的gif太快,是否是沒發現這個方法的一個問題呢?

來個靜態截圖:

 

沒看出來?那看下邊這個圖:

發現了嗎?

div.box 我並無設置寬度,可是他默認展現的最大寬度(在沒有border和padding的狀況下),是父元素(body)寬度的50%!

後來我就想由於什麼?

在張鑫旭大神的absolute課程中,講過方位值left和right這些,若是設置50%,是從父元素本來寬度的50%處開始左邊距的。(固然這不是人家的原話,是個人理解)。

也就是說,在我不設置right的狀況下,left:50%;也就至關於這個box盒子剩下的活動空間就是從left: 50% 到 最右邊了。

 要說明這個,其實直接去掉transform的居中效果就能夠一眼看出來了:

 若是再狠點,right也設置50%,那box的寬度就被擠沒了。

 

發現這個問題後,我恍然大悟雖然這個方法很好用,可是他仍是有不少侷限性。最好只用在垂直居中上,畢竟有不少場景不適用。

好比這種:

我要想要中間那塊根據文案的多少,寬度自適應,而且還能永遠水平居中的話,就不適用上邊這種方案,否則會發生車禍現場:

那麼,這種狀況的水平居中該怎麼作呢?

一眼明瞭,水平居中簡單吧!直接給內聯元素的父親設置text-align就好了。

 

不過最近我又發現了原理差很少的另外一種absolute定位元素實現居中的寫法,現補充以下:(2019-01-08 14:45:04 )

【很是】 六加1、寬高可定可不定的全屏垂直居中效果

上下左右0+自適應的margin實現

以下:

給一個寬高300的定位元素垂直水平居中。

* 注意這裏寬高300雖然有要求,可是經我實際測試,寬高自動增刪都不影響垂直水平居中,說明在寬高不定的元素中,也就能夠實現。

不說廢話了,代碼以下:

<div class="clas class3">test3</div>

 css:

 

7、圖片和多行文本兩列的垂直居中(經典佈局難題)

一、兄弟們一塊兒 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;

 

 

8、堪稱萬能鑰匙的公共垂直居中解法。無視父元素高度是否固定!無視文字多少行!

 

(一)靈魂輔助的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 屬性,

注意 IE六、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>

  這種方法的好處是不用添加多餘的無心義的標籤,但缺點也很明顯,它的兼容性不是很好,不兼容 IE六、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/

相關文章
相關標籤/搜索