能夠讓不定寬高元素水平和垂直居中的方法

在開發(fā)中經(jīng)常遇到這個(gè)問題冠王,即讓某個(gè)元素的內(nèi)容在水平和垂直方向上都居中,內(nèi)容不僅限于文字蝌以,可能是圖片或其他元素。而且我們希望不要涉及寬度和高度何之,也就是說跟畅,我們不知道父元素的寬高,也不知道內(nèi)容元素的寬高溶推。這篇文章就來總結(jié)一下都有哪些方法可以實(shí)現(xiàn)水平和垂直都居中徊件。

不適合的方案

text-align和line-height

顯然奸攻,使用text-align和line-height的方式更適合單排文字,而不適合本文的需求庇忌。特別是line-height舞箍,無法保證在不知道高度的情況下還能垂直居中。而且就算是文字皆疹,我們也不知道文字有多少行疏橄。

position:absolute、50%和margin:-px

絕大多數(shù)情況下略就,我們可以考慮這種方案捎迫,讓想要居中的元素通過定位和margin為負(fù)值進(jìn)行偏移的方法讓它在垂直方向上居中。這種方案不要求父元素的高度表牢,也就是即使父元素的高度變化了窄绒,仍然可以保持在父元素的垂直居中位置,水平方向上是一樣的操作崔兴。但是這里有一個(gè)問題彰导,就是我們的需求往往是內(nèi)部的這個(gè)元素的寬度高度也不確定,比如是一段文字敲茄,你無法保證這段文字的字?jǐn)?shù)多少位谋,所以通過margin為負(fù)值來偏移在這種情況下行不通。

position:fixed堰燎、0和margin:auto

當(dāng)我們要制作一個(gè)modal dialog彈出框時(shí)掏父,比如彈出居中于屏幕的廣告或登錄框。這個(gè)時(shí)候可以考慮一些相對(duì)于窗口或網(wǎng)頁居中的方案秆剪。

<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;赊淑,對(duì)于塊級(jí)元素而言,確定了自己的寬度之后仅讽,margin:auto可以幫助它居中陶缺,即使在position:fixed時(shí)。不過必須規(guī)定要居中的元素的寬高度洁灵,無法滿足我們的需求饱岸。

position:absolute、0和margin:auto

上面的fixed方案只適合在整個(gè)窗口實(shí)現(xiàn)居中处渣。fixed會(huì)使元素脫離網(wǎng)頁,因此在內(nèi)容流中還是不適用蛛砰。在內(nèi)容流中也想實(shí)現(xiàn)居中罐栈,可以如下:

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

首先是仿造上面一個(gè)方法,使用margin:auto泥畅,只不過使用absolute荠诬。使用absolute定位的話,父級(jí)元素必須也具有position(不為static)。所以把.inner放在一個(gè)有position的父級(jí)元素.inner-wrapper柑贞。這樣.inner相對(duì)于.inner-wrapper就是居中的(前提還是.inner要有寬高)方椎。同理因?yàn)橐O(shè)定寬高,所以不滿足我們的需求钧嘶。

正確的方案

1棠众、display:table和diaplay:table-cell

這個(gè)方案是理解上最容易的,因?yàn)閠able具備垂直居中的屬性有决,所以很容易通過屬性就能實(shí)現(xiàn)闸拿。

<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的寬高书幕,當(dāng)內(nèi)部的內(nèi)容仍然保持居中狀態(tài)新荤。

2、position:absolute台汇、50%和translate

在css3里面提供了translate函數(shù)苛骨,它的主要作用是位移,傳給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%)將會(huì)將元素位移自己寬度和高度的-50%。這種方法其實(shí)和最上面被否定掉的margin負(fù)值用法一樣掠抬,可以說是margin負(fù)值的替代方案吼野。這樣你就非常容易理解了。這個(gè)方法最厲害的地方是不需要確定.inner的寬高两波,而.container的寬高也不需要手動(dòng)設(shè)置瞳步,如果它自己本身就被撐大的話。這里只是為了演示方便腰奋,才特意給它設(shè)置了寬高单起。

3、vw vh和translate

vh和vw是兩個(gè)比較偏的單位劣坊,是指“viewport的height和width的1%”嘀倒,比如說50vh就是當(dāng)前視口(窗口的高度,實(shí)驗(yàn)中包含了滾動(dòng)條)高度的50%局冰。也就是說vw將獲得和1%差不多的window寬度测蘑。因此用在fixed的時(shí)候更加適合

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

其實(shí)和使用50%沒有太大的差別康二,因?yàn)檫@時(shí)top碳胳、left取的50%是相對(duì)于父元素的,和margin沫勿、padding不一樣挨约。如果非得要margin的話味混,就可以從這里衍生出變體:

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

vh vw只能從窗口的大小去考慮,不適合正常的文本流诫惭。不過有的時(shí)候可以非常有用翁锡,特別是在做全屏應(yīng)用的時(shí)候,比如full page夕土。

4馆衔、:before和display:inline-block

這也是一種處理方式,通過偽類:before在元素內(nèi)增加新元素后在用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>

這個(gè)方案是比較特別一些,不是很好理解梨熙。首先开镣,.container水平居中沒問題。接著咽扇,給.container偽類:before設(shè)定為height:100%邪财,這樣可以用一個(gè)偽元素在.container獲得與父元素等高的空間。然后用inline-block和vertical-align: middle改變對(duì)齊的基線质欲,關(guān)于這一點(diǎn)树埠,我也不甚懂,這里有一篇文章可以參考嘶伟。通過:before之后怎憋,.container內(nèi)的行級(jí)元素的對(duì)齊基線就跑到居中的位置,也就實(shí)現(xiàn)了垂直居中對(duì)齊九昧。這個(gè)時(shí)候绊袋,如果里面僅一排文字,其實(shí)可以不用.inner铸鹰,但是上面的例子里面有一個(gè)<br>癌别,這就不一樣了。如果直接把文字放在.container里面蹋笼,
之前的文字會(huì)基于:before基線展姐,會(huì)保持垂直對(duì)齊的狀態(tài)。但是
之后的文字會(huì)另起一行剖毯,這一行將起始于:before的下一行圾笨,所以會(huì)在:before的100%高度下面,導(dǎo)致被頂出.container逊谋。但是如果把文字放在.inner里面擂达,再讓.inner為inline-block,就可以使.inner和:before處于同一基線涣狗,這樣就讓整個(gè).inner處于垂直居中的狀態(tài)谍婉。

5、css3 flex

css3新增了布局相關(guān)的屬性镀钓,其中flex布局可以非常簡(jiǎn)單地幫我們實(shí)現(xiàn)我們想要的效果穗熬。

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

簡(jiǎn)單解釋一下,當(dāng)display: flex時(shí)丁溅,表示該容器內(nèi)部的元素將按照flex進(jìn)行布局唤蔗。align-items: center表示這些元素將相對(duì)于本容器水平居中,justify-content: center也是同樣的道理垂直居中窟赏。對(duì).container賦予了這些樣式之后妓柜,作為它的內(nèi)部元素.inner自己自覺的居中了。而且這里你會(huì)發(fā)現(xiàn)涯穷,由于沒有使用text-align: center棍掐,.inner里面的文字是不會(huì)居中的,也就是說僅僅.inner這個(gè)容器居中而已拷况。

總結(jié)

從上面的幾種可行的方案作煌,大致可以分為兩類:display對(duì)齊方案、translate位移方案赚瘦。display方案是充分發(fā)揮css的布局特性粟誓,利用布局和UI引擎的特性來控制布局中的對(duì)齊方式。而translate方案則是利用位移起意,通過先50%的位移鹰服,可以是通過position,也可以是通過margin vw vh揽咕,但是完成之后悲酷,在通過translate把元素拉回去,之所以用translate而不是margin是因?yàn)閠ranslate是相對(duì)于元素本身心褐,而margin不是舔涎。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市逗爹,隨后出現(xiàn)的幾起案子亡嫌,更是在濱河造成了極大的恐慌,老刑警劉巖掘而,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挟冠,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡袍睡,警方通過查閱死者的電腦和手機(jī)知染,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斑胜,“玉大人控淡,你說我怎么就攤上這事嫌吠。” “怎么了掺炭?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵辫诅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我涧狮,道長(zhǎng)炕矮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任者冤,我火速辦了婚禮肤视,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涉枫。我一直安慰自己邢滑,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布愿汰。 她就那樣靜靜地躺著殊鞭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尼桶。 梳的紋絲不亂的頭發(fā)上操灿,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音泵督,去河邊找鬼趾盐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛小腊,可吹牛的內(nèi)容都是我干的救鲤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼秩冈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼本缠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起入问,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤丹锹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后芬失,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楣黍,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年棱烂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了租漂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哩治,靈堂內(nèi)的尸體忽然破棺而出秃踩,到底是詐尸還是另有隱情,我是刑警寧澤业筏,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布吞瞪,位于F島的核電站,受9級(jí)特大地震影響驾孔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜惯疙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一翠勉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧霉颠,春花似錦对碌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诉位,卻和暖如春骑脱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背苍糠。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國打工叁丧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岳瞭。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓拥娄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親瞳筏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子稚瘾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容