不定元素寬高用css實現內容水平和垂直都居中

在開發中常常遇到這個問題,即讓某個元素的內容在水平和垂直方向上都居中,內容不只限於文字,多是圖片或其餘元素。並且咱們但願不要涉及寬度和高度,也就是說,咱們不知道父元素的寬高,也不知道內容元素的寬高。這篇文章就來總結一下都有哪些方法能夠實現水平和垂直都居中。css

不適合的方案

text-align和line-height

顯然,使用text-align和line-height的方式更適合單排文字,而不適合本文的需求。特別是line-height,沒法保證在不知道高度的狀況下還能垂直居中。並且就算是文字,咱們也不知道文字有多少行。html

position:absolute、50%和margin:-px

絕大多數狀況下,咱們能夠考慮這種方案,讓想要居中的元素經過定位和margin爲負值進行偏移的方法讓它在垂直方向上居中。這種方案不要求父元素的高度,也就是即便父元素的高度變化了,仍然能夠保持在父元素的垂直居中位置,水平方向上是同樣的操做。可是這裏有一個問題,就是咱們的需求每每是內部的這個元素的寬度高度也不肯定,好比是一段文字,你沒法保證這段文字的字數多少,因此經過margin爲負值來偏移在這種狀況下行不通。css3

position:fixed、0和margin:auto

當咱們要製做一個modal dialog彈出框時,好比彈出居中於屏幕的廣告或登陸框。這個時候能夠考慮一些相對於窗口或網頁居中的方案。app

<style>
 .container {
   position:fixed;
   top:0;
   right:0;
   bottom:0;
   left:0;
   margin:auto;
 }
</style>

<div class="container" style="width: 300px; height: 200px; background: #f1f1f1">
 this is a box fixed in center of screen
</div>

這裏面最重要的是margin: auto;,對於塊級元素而言,肯定了本身的寬度以後,margin:auto能夠幫助它居中,即便在position:fixed時。不過必須規定要居中的元素的寬高度,沒法知足咱們的需求。函數

position:absolute、0和margin:auto

上面的fixed方案只適合在整個窗口實現居中。fixed會使元素脫離網頁,所以在內容流中仍是不適用。在內容流中也想實現居中,能夠以下:佈局

<style>
    .container {
        position: relative;
    }
    .inner-wrapper {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
    }
    .inner {
        position:absolute;
        top:0;
        right:0;
        bottom:0;
        left:0;
        margin:auto;
    }
</style>

<div class="container">
    <p>This is a p</p>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

    <div class="inner-wrapper"><div class="inner" style="width: 300px;height: 200px;background: #f1f1f1">
        this is a box fixed in center of screen
    </div></div>
</div>

首先是仿造上面一個方法,使用margin:auto,只不過使用absolute。使用absolute定位的話,父級元素必須也具備position(不爲static)。因此把.inner放在一個有position的父級元素.container。這樣.inner相對於.container就是居中的(前提仍是.inner要有寬高)。接下來的問題就是怎樣讓.container具有和內容相同的高寬,經過.container的父級元素爲position:relative,.container爲absolute,再使用100%使.container和父級元素寬高相同便可。同理由於要設定寬高,因此不知足咱們的需求。flex

正確的方案

display:table和vertical-align:middle

這個方案是理解上最容易的,由於table具有垂直居中的屬性,因此很容易經過屬性就能實現。this

<style>
.container {
  display: table;
}
.inner {
  display: table-cell;
  vertical-align:middle;
  text-align:center;
}
</style>

<div class="container">
  <div class="inner">
    you own content
  </div>
</div>

這種狀況下,咱們能夠經過隨意改變.inner的寬高,當內部的內容仍然保持居中狀態。.net

DEMOcode

position:absolute、50%和translate

在css3裏面提供了translate函數,它的主要做用是位移,傳給transform屬性。

<style>
.container {
  position: relative;
}
.inner {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>

<div class="container">
  <div class="inner">
    your own content
  </div>
</div>

html代碼和上面同樣。translate(-50%, -50%)將會將元素位移本身寬度和高度的-50%。這種方法其實和最上面被否認掉的margin負值用法同樣,能夠說是margin負值的替代方案。這樣你就很是容易理解了。這個方法最厲害的地方是不須要肯定.inner的寬高,而.container的寬高也不須要手動設置,若是它本身自己就被撐大的話。這裏只是爲了演示方便,才特地給它設置了寬高。

DEMO

vw vh和translate

vh和vw是兩個比較偏的單位,是指「viewport的height和width的1%」,好比說50vh就是當前視口(窗口的高度,實驗中包含了滾動條)高度的50%。也就是說1vw將等於和1%的window寬度差很少的值。所以用在fixed的時候更加適合。

<style>
 .inner {
   position:fixed;
   top: 50vh;
   left: 50vw;
   transform: translate(-50%, -50%);
 }
</style>

<div class="inner">
    this is a box fixed in center of screen
</div>

其實和使用50%沒有太大的差異,由於這時top、left取的50%是相對於父元素的,和margin、padding不同。若是非得要margin的話,就能夠從這裏衍生出變體:

.inner2 {
   position:fixed;
   top: 0;
   left: 0;
   margin: 50vh 0 0 50vw;
   transform: translate(-50%, -50%);
 }

vh vw只能從窗口的大小去考慮,不適合正常的文本流。不過有的時候能夠很是有用,特別是在作全屏應用的時候,好比full page。我把兩種方案都放在了演示中,你能夠在DEMO查看。

DEMO

:before和display:inline-block

這也是一種處理方式,經過僞類:before在元素內增長新元素後在用display:inline-block,經過高度的處理獲得想要的效果。

<style>
.container{
    text-align: center;
}

.container:before {
    content: '';
    display: inline-block;
    height: 100%;
    vertical-align: middle;
}
.inner {
    display: inline-block;
}
</style>

<div class="container">
    <div class="inner">
        this is a box fixed in center of screen<br>The second line
    </div>
</div>

這個方案是比較特別一些,不是很好理解。首先,.container水平居中沒問題。接着,給.container僞類:before設定爲height:100%,這樣能夠用一個僞元素在.container得到與父元素等高的空間。而後用inline-block和vertical-align: middle改變對齊的基線,關於這一點,我也不甚懂,這裏有一篇文章能夠參考。經過:before以後,.container內的行級元素的對齊基線就跑到居中的位置,也就實現了垂直居中對齊。這個時候,若是裏面僅一排文字,其實能夠不用.inner,可是上面的例子裏面有一個<br>,這就不同了。若是直接把文字放在.container裏面,<br>以前的文字會基於:before基線,會保持垂直對齊的狀態。可是<br>以後的文字會另起一行,這一行將起始於:before的下一行,因此會在:before的100%高度下面,致使被頂出.container。可是若是把文字放在.inner裏面,再讓.inner爲inline-block,就可使.inner和:before處於同一基線,這樣就讓整個.inner處於垂直居中的狀態。

DEMO

css3 display:flex

css3新增了佈局相關的屬性,其中flex佈局能夠很是簡單地幫咱們實現咱們想要的效果。

<style>
.container {
    display: flex;
    align-items: center;
    justify-content: center;
}
</style>

<div class="container">
    <div class="inner">
        this is a box fixed in center of screen<br>The second line
    </div>
</div>

簡單解釋一下,當display: flex時,表示該容器內部的元素將按照flex進行佈局。align-items: center表示這些元素將相對於本容器水平居中,justify-content: center也是一樣的道理垂直居中。對.container賦予了這些樣式以後,做爲它的內部元素.inner本身自覺的居中了。並且這裏你會發現,因爲沒有使用text-align: center,.inner裏面的文字是不會居中的,也就是說僅僅.inner這個容器居中而已。

DEMO

總結

從上面的幾種可行的方案,大體能夠分爲兩類:display對齊方案、translate位移方案。display方案是充分發揮css的佈局特性,利用佈局和UI引擎的特性來控制佈局中的對齊方式。而translate方案則是利用位移,經過先50%的位移,能夠是經過position,也能夠是經過margin vw vh,可是完成以後,在經過translate把元素拉回去,之因此用translate而不是margin是由於translate是相對於元素自己,而margin不是。


本文發表在個人博客 http://www.tangshuang.net/319...若有疑問或不足之處,請到博客留言

相關文章
相關標籤/搜索