Yijen's blog

關於部落格
繪圖 | 食記 | Web前端技術 | HTML | CSS | JavaScript 研究
  • 324196

    累積人氣

  • 60

    今日人氣

    0

    訂閱人氣

更多 CSS 達成 Div 垂直置中的方法研究 (CSS Vertical Centering Complete Guide)

center

 

而它的原理其實也不難理解,就是「利用偽元素」在外框裡面塞入一個和外框等高的 inline-block 行內元素,它是不被看到的,如此一來,在外框裡面的其它高度沒有100%的行內元素也可以遵循 vertical-align: middle 的方法去排隊了。用一張圖來解釋的話就是這樣↓

優點

很簡單,效果卻出奇地好

缺點

沒有明顯的缺點,除非你想「垂直置中」的元素是複數,在水平想要做 float left or right 則無法兩者兼顧

沒有固定高度,即高度不確定的多行內容是否也能垂直置中?

令人驚訝的是,這個方法居然也是可行的!只要做一點小修改,將外層加上 font-size: 0;,並將原本的 .center 的高度值拿掉,dom元素由 div 換成 p 即可,但是要記得將目標的 font-size 給加回來,否則文字就看不見了,理由是 font-size 會繼承。

HTML

<div class="wrapper">
  <p class="text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatibus suscipit explicabo unde sit atque exercitationem delectus qui ipsam, at. Vitae veritatis officia quidem commodi repudiandae illum cum, quisquam voluptatibus quaerat.</p>
</div>

CSS

.wrapper {
  height: 250px;
  background-color: #9096A6;
  text-align: center;

  /* Point */
  font-size: 0;
}
.wrapper:before {
  content: "";
  height: 100%;
  display: inline-block;
  vertical-align: middle;
}
p.text{
  display: inline-block;
  vertical-align: middle;

  /* Point 要使用絕對值的 font-size 覆寫掉父層的 font-size: 0 */
  font-size: 15px;
}

Demo

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatibus suscipit explicabo unde sit atque exercitationem delectus qui ipsam, at. Vitae veritatis officia quidem commodi repudiandae illum cum, quisquam voluptatibus quaerat.


Nam maiores nulla voluptas nostrum quibusdam! Laboriosam dignissimos debitis provident ad et in facere voluptas, voluptate delectus ullam optio numquam soluta eligendi beatae vero quasi amet magnam. Facilis inventore cupiditate ducimus voluptatum dicta quam fugit totam placeat iste rem in quisquam sint deserunt accusamus natus necessitatibus velit, aut voluptatibus quae consectetur beatae nam vel officia ex. Distinctio quae totam dolor laudantium pariatur, explicabo unde voluptatibus voluptates, est quia doloremque quas nam. Natus modi odio, dolor cumque nam voluptate harum commodi hic, numquam saepe perferendis necessitatibus ducimus, cum quo rem sunt enim et impedit non dolorem. Animi quidem ipsam quaerat ea, saepe officiis impedit praesentium rerum! Dolor, aut iste aliquid voluptatibus nulla. Tenetur fuga, in eaque architecto vel natus laborum ducimus.

延伸題:「如果是有二段以上的文字,也可以整體都 垂直置中 嗎?」

HTML

<div class="wrapper">
  <div class="text">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque, in.</p>
    <p>Modi excepturi voluptatibus expedita voluptas laborum veritatis error adipisci doloremque. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid cum asperiores dicta, magnam quibusdam veniam nemo aperiam sit quas fugiat?</p>
    <p>Modi excepturi voluptatibus expedita voluptas laborum veritatis error adipisci doloremque. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid cum asperiores dicta, magnam quibusdam veniam nemo aperiam sit quas fugiat?</p>
  </div>
</div>

Demo

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque, in.

Modi excepturi voluptatibus expedita voluptas laborum veritatis error adipisci doloremque. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid cum asperiores dicta, magnam quibusdam veniam nemo aperiam sit quas fugiat?

Modi excepturi voluptatibus expedita voluptas laborum veritatis error adipisci doloremque. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid cum asperiores dicta, magnam quibusdam veniam nemo aperiam sit quas fugiat?

哈!測試結果是可以的哦,只要把原本單一個 p.text 用 div.text 取代,再將正常的複數文字段落 p 塞在被置中過的 div.text 就可以囉。

個人覺得這一版的 CSS 垂直置中(vertical centering)技巧不僅寫的 Code 很少,應用方式又多,在實戰應用上可以說是超級方便呀!在這裡要向發明這個 CSS 技巧的神人致敬!

簡易方法A - 利用 CSS3 的 transform: translate

本方法適用於外層高度已知(或固定),但內容為未知高度的 Block 元素垂直置中

HTML

<div class="wrapper3">
  <div class="child block">
    I am a unknown height block level box
  </div>
</div>

CSS

.wrapper3 {
    position: relative;
}
.wrapper3 .child {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
}

Demo

I am a unknown height block level centered element.
I am a unknown height block level centered element. maybe two lines or three lines? it doesn't matter. I will be always centered anyway.

CSS看起來有沒有覺得似曾相識?呵,本方式和之前其中一個方法,利用 top: 50% 再設 margin-top: (本体高度一半的負值) 原理一樣,只是用 css3 的 transform: translateY 更聰明,可以直接設為負50%,也就是不必知道本身的高度也可以達成垂直置中的目的。

缺點

因為被置中的元素必須為絕對定位,所以在實務應用上可能會有點難用。

簡易方法B - Block 級元素設置上下一樣的 padding

這方法其實算有點偷懶啦,但其實有的時候,你想要的效果不就只是這樣而已嗎?XD
沒有一定最好用的CSS,只有最適合用的CSS

HTML

<div class="menu-demo">
  <div class="child">Home</div>
  <div class="child">Store</div>
  <div class="child">About</div>
</div>

CSS

.menu-demo {
    text-align: center;
    background-color: indianred;
    padding: 6px 0;
}
.menu-demo .child {
    min-width: 120px;
    display: inline-block;
    text-align: center;
    color: #E00;
    background-color: pink;

    /* Point */
    padding-top: 30px;
    padding-bottom: 30px;
}

demo

demo2

優點

根本就超級偷吃步,秒懂 XD。
另外,比起 height = line-height 作法來說,它是可以斷行的(如果只有它自己一個的話啦),兩個以上群組還是建議高度一致,如上面展示。

缺點

只適合小東西用,Menu or Button 等等,或是有時候你的元素因某些原因無法設置 padding 時就沒辦法用。

方法C: 很多不同比例圖片同時陳列時的垂直置中法 - CSS3 Object fit

Example

購物網站常有的 Layout 比例不一的產品照片列表

如果是你,你會怎麼刻 HTML Layout 呢?大概會像這個樣子吧

HTML

<div class="prod">
    <img src="http://placehold.it/130x130" class="prod-thumbnail">
    <div class="prod-caption">This is a good product</div>
</div>

CSS

.prod {
    float: left;
    width: 200px;
    min-height: 200px;
    border: 1px solid #747474;
    margin-right: 10px;
    padding: 10px;
    box-sizing: border-box;
}
.prod-thumbnail {
    display: block;
    margin: 0 auto;
}
.prod-caption {
    line-height: 1.2;
    font-size: 12px;
    margin: 6px auto;
}

Demo - Before

This is a good product
This is also a good product
This is a bad product

最常遇到的例子就是:當你接到電子商務網站的案子,需要做「圖文式產品列表頁」的時候,絕大多數的案例,業者並不會提供你「固定比例」的圖片,一定是有正方、有長、有扁,比例都不同,水平置中當然沒問題,垂直呢?哈哈哈,搞死你……

上面的 mockup 刻出來之後,就會像樂天網站的 Layout 一樣,直方型和正方形品圖都是水平+垂直置中的沒問題,但是扁長型的圖片就只能靠上齊了。

當然,這個時候,你可以用上面新增 :before 偽類的方法在 .prod 加一些 css 來調整,但注意到這裡的矩型裡面除了圖片之外,還有文字,所以你要考慮的地方不是很單純。

有另一個更簡單的方式,就是用 CSS3 針對 image 提供的新屬性 object-fit 設定為 contain 就可以完美達成任務。

CSS

.prod-thumbnail {
    display: block;
    margin: 0 auto;

    /* Point */
    width: 130px;
    height: 130px;
    object-fit: contain; /* 在130正方的空間完整地將圖片顯示出來 */
}

Demo - After (PS:淺藍底色是為 demo 加上的,object-fit 本身不會在 image 背景加色)

This is a good product
This is also a good product
This is a bad product

object-fit 是目前最新的 css3 image 屬性,它的用途很直覺且很強大。object-fit 更好玩的除了 contain 還有 cover,目前坊間看到許多「整頁背景」部分就是利用另一個相似用途的 background-size: cover 來做的。如果你對它有興趣可以去 Google 一下 :D 或是改天再來寫篇專文介紹。

優點

一行 css 就解決了圖片垂直置中,你以前還要寫一堆 css hack 或 javascript !!!

缺點

支援度尚無法稱為完整,在本文撰寫時間點(2015.02.13)時,firefox 最新版(35.0)尚無支援,但好消息是下一版本(36.0)的 firefox 即將支援 css3 的 object-fit。
IE? 就別理它了吧……XDDD 詳細的 Support list 請至這裡查看

方法D - 你有聽過安麗嗎?噢不!是 flexbox

同方法C一樣,是 CSS3 很強大的屬性,如果你有聽過 flexbox 且知道怎麼做,css vertical centering 根本是 piece of cake!

CSS

.parent {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

Demo

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quasi reiciendis deleniti, vel incidunt beatae magnam consequatur dolor ipsa quo quis rem odio totam, amet veritatis, itaque praesentium numquam? Et, nesciunt!

結論:純 CSS Vertical Centering Div 垂直置中是可以做到,而且方法非常多元的。

引用及參考來源

相簿設定
標籤設定
相簿狀態