摘要:子容器溢出時,父容器出現(xiàn)滾動條。父容器或很顯然,子容器溢出時,被父容器截斷的情形無法和父容器自適應(yīng)于子容器共存?,F(xiàn)在這個布局可以自動生成,詳見林小志的小工具圖片垂直居中。溢出子容器溢出時會變成頂對齊,原因同上。
本文在evernote里有備份。如果evernote的閱讀區(qū)域嫌窄了,那么可以把這個鏈接拖入書簽并點擊javascript:jQuery("#container").width(980);
本文從這個回答整理而來。對于當(dāng)今出現(xiàn)的一些CSS垂直居中的方案,這篇文章將會系統(tǒng)地審視它們,從實用角度進(jìn)行評估。
不羅嗦,先上圖:
考量需求及難度為避免混淆,本文中所說的父容器和子容器都不是相對的,而對應(yīng)著如下文檔結(jié)構(gòu)里面的.outer和.inner容器:
......
我們從如下角度來評估:
父容器/子容器的高度是否可變
是否需要手工計算
子元素溢出時父元素是截斷、被撐高還是保留滾動條
當(dāng)然,還有兼容性
高度相關(guān)代碼 | 效果 |
---|---|
height:100px; | 定高 |
height:auto | 不定高,自適應(yīng)于自身的content-box |
height:50% | 不定高,自適應(yīng)于包含塊 |
出現(xiàn)了 3(定高/自適應(yīng)于外部/自適應(yīng)于內(nèi)部) ^ 2 (父容器/子容器) =9 種情形,搭配見下:
父容器 | 子容器 | 難度 | 解(tu)說(cao) |
---|---|---|---|
定高 | 定高 | 簡單 | 快速開發(fā)時就是這樣 |
定高 | 自適應(yīng)于內(nèi)部 | 稍難 | 常見的需求 |
定高 | 自適應(yīng)于外部 | 簡單 | 手工算一算就好了 |
自適應(yīng)于內(nèi)部 | 定高 | 簡單 | 變相定高,高度放在內(nèi)層,方便解耦 |
自適應(yīng)于內(nèi)部 | 自適應(yīng)于內(nèi)部 | 稍難 | 留白固定,罕見的需求 |
自適應(yīng)于內(nèi)部 | 自適應(yīng)于外部 | WTF | 折騰出這種需求,不覺得害臊嗎 |
自適應(yīng)于外部 | 定高 | 困難 | 適配所有屏幕的slideshow |
自適應(yīng)于外部 | 自適應(yīng)于內(nèi)部 | 困難 | 普適性更高的slideshow |
自適應(yīng)于外部 | 自適應(yīng)于外部 | 稍難 | 一個模塊(或大小不定的頭像),出現(xiàn)在大小不定的位置 |
子容器溢出代表子容器高度大于父容器高度的情形。
子容器溢出時,被父容器截斷。父容器overflow:hidden。
子容器溢出時,把父容器撐高。父容器height:auto;overflow:visible或display:table-cell等等。
子容器溢出時,父容器出現(xiàn)滾動條。父容器overflow:scroll或overflow:auto
很顯然,子容器溢出時,被父容器截斷的情形無法和父容器自適應(yīng)于子容器共存。
兼容性IE6、IE7:老而不死的瀏覽器,瀏覽器尚未統(tǒng)一、IE一家獨大之時的遺毒,一大堆bug等著你。
IE8:IE8起全面支持CSS2.1,剩下一些稍微少坑爹那么一點點的bug。
IE9。尷尬的產(chǎn)物,微軟第一次搭上CSS3的末班車。
IE10+與其他現(xiàn)代瀏覽器(終于可以和其他瀏覽器并列了……IE10淚目)。
4、3、2、1的兼容難度是一步步變難,兼容到4、3、2、1所對應(yīng)的代碼量/工作量是100%、102%、120%、300%的關(guān)系。
在這里僅僅考量IE6/7,IE8的無bug實現(xiàn)的兼容性。IE9+的兼容性,對于文中提到的所有方案都是可行的。
其他是否需要手動計算/需要calc屬性進(jìn)行輔助計算
如果需要手動計算,若界面進(jìn)行重構(gòu),而居中的需求不變,就需要重新計算。比較費時費事。布局也相對不夠靈活。
方案匯總CSS 版本 | 布局類型 | 方案 |
---|---|---|
CSS 2.1 | 普通流,塊級布局 | 父容器上下等padding |
子容器上下等margin | ||
普通流,行內(nèi)布局 | 父容器line-height=height | |
子容器所在的line-box的line-height=父容器的height | ||
普通流,塊級table布局 | 父容器display:table-cell,子容器vertical-align | |
子容器被table、tr、td包裹 | ||
絕對定位布局 | 子容器絕對定位,top:50%,負(fù)margin | |
子容器絕對定位,top:0,bottom:0,margin:auto | ||
普通流,塊級布局 | background代圖片background-position | |
CSS3 | 絕對定位布局 | 子容器絕對定位,top:50%,translateY(-50%) |
普通流,塊級布局 | backgournd代圖片backgournd-size | |
普通流,flexbox布局 | flexbox |
方案 | 兼容性 | 父容器 | 子容器 | 子容器溢出 | 其他 | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|
IE8 | IE6/7 | 定高 | 自適應(yīng)于內(nèi)部 | 自適應(yīng)于外部 | 定高 | 自適應(yīng)于內(nèi)部 | 自適應(yīng)于外部 | 撐高 | 被截斷 | 不需手工計算 | |
父容器上下等padding | √ | √ | √ | √* | × | √ | √* | × | √ | √* | × |
子容器上下等margin | √ | √ | √ | √* | × | √ | √* | × | √ | × | × |
background代圖片background-position | √ | √ | √ | √ | √ | √ | × | × | × | √ | √ |
最基礎(chǔ)的方案就是這樣,手工算好每一個容器的高度和補(bǔ)白/位移需要的內(nèi)容,簡單粗暴:
/*父子均定高,父容器上下等padding*/ .outer{ height: 100px; padding-top: 40px ; } .inner{ height: 100px; }
/*父子均定高,子容器上下等margin*/ .outer{ height: 180px; overflow: hidden; *zoom: 1; }/*父容器給予BFC以避免子容器margin并到父容器上*/ .inner{ height: 100px; margin-top: 40px ; }
父子都需要自適應(yīng)于內(nèi)部時:
/*父子均自適應(yīng)于內(nèi)部,父容器上下等padding*/ .outer{ height: auto; padding-top: 40px ; padding-bottom: 40px ; } .inner{ height: auto; }
/*父子均自適應(yīng)于內(nèi)部,子容器上下等margin*/ .outer{ height: auto; overflow: hidden; *zoom: 1; }/*父容器給予BFC和haslayout,以避免子容器margin并到父容器上*/ .inner{ height: auto; margin-top: 40px ; margin-bottom: 40px ; }
說明:
需求:父子都需要自適應(yīng)于內(nèi)部的解決方案里,是把留白的高度固定,這種需求其實很少見。
可缺省:height:auto可以省去,這是默認(rèn)值。
對于塊級元素,默認(rèn)是height:auto;width:auto;
width的auto值是自適應(yīng)于這個元素的包含塊的寬度,而height自適應(yīng)于這個元素的content-box的高度
自適應(yīng):父子容器均可以自適應(yīng)于內(nèi)部;也可以父容器自適應(yīng),子容器定高。
因為height:auto時,計算高度值的依賴方向是從外往內(nèi)。
自適應(yīng):為何在這倆方案里不容許出現(xiàn)父容器或子容器自適應(yīng)于外層呢?
因為對于height來說,它的百分比值是乘以包含塊的height,但padding-top/padding-bottom/margin-top/margin-bottom的百分比值是乘以包含塊的width,而非我們希望的height。
溢出:
* 父容器上下等padding時,父容器定高時,子容器溢出padding-edge的部分會被截斷。
* 子容器上下等margin時,父容器自適應(yīng)于內(nèi)部,父容器只會被撐高,永遠(yuǎn)無法被截斷。
* 其他情形,截斷都沒有什么意義
在子容器是標(biāo)簽時,可以直接使用background來替代它。也可以算得上一種方案。
.inner { background-image: url("..."); background-position: 50% 50%;/*注,火狐不支持background-position-y的屬性設(shè)置*/ }
說明:
自適應(yīng):無法自適應(yīng)于外部容器,CSS2.1階段,background無法相對于容器伸縮。
溢出:背景溢出的情形,直接會被截斷。
其他:你甚至可以把inner的標(biāo)簽省掉,直接把背景放到outer之上
2. 普通流,行內(nèi)布局 (css2.1)方案 | 兼容性 | 父容器 | 子容器 | 子容器溢出 | 其他 | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|
IE8 | IE6/7 | 定高 | 自適應(yīng)于內(nèi)部 | 自適應(yīng)于外部 | 定高 | 自適應(yīng)于內(nèi)部 | 自適應(yīng)于外部 | 撐高 | 被截斷 | 不需手工計算 | |
父容器line-height=height | √* | × | √ | × | × | √ | √ | √ | √ | × | √ |
子容器所在的line-box的line-height=父容器的height | √* | √* | √ | × | √ | √ | √ | √ | √ | × | √ |
“父容器line-height=height”,這個方案在于將子容器當(dāng)做行內(nèi)元素呈遞,并設(shè)置vertical-align,line-box和block-box的高度持平,就完成了垂直居中的的效果。
.outer { line-height: 100px; height: 100px; font-size: 0; } .inner { display:inline-block; vertical-align:middle; font-size: 16px; }
為何需要font-size:0?因為vertical-align:middle的定義是:元素的中垂點與父元素的基線加1/2父元素中字母x的高度對齊。因此在font-size>0時,元素將會在baseline上出現(xiàn)一定的偏移,偏移量跟這個字號下的x字母的高度有關(guān)。
可以在jsFiddle中看到對比:
不使用font-size:0:
http://jsfiddle.net/humphry/haaaM/
使用font-size:0:
http://jsfiddle.net/humphry/7zCEm/
說明:
兼容性:沒有涉及relative和absolute定位,布局時相對無痛。
兼容性:這個方案是IE67不支持的,原因不詳(只知道inline-block和vertical-align的標(biāo)準(zhǔn)誕生于IE8之后),也沒有時間研究。2014年了,有點追求好嗎。
自適應(yīng):子容器可以輕松做到自適應(yīng)于內(nèi)部、外部或者定高,但在這個方案里,父容器必須定高,因為line-height的百分比單位是相對font-size來說的。
溢出:子容器溢出時會變成頂對齊,這是因為,line-box 的高度跟內(nèi)部最高的 inline-box 相等,因而line-box 可以被撐高,從上往下排一個個排列下來,從而失去了居中的效果。換句話說,子元素溢出時,父容器可以自適應(yīng)于內(nèi)部。
其他:line-height和font-size是一個可以繼承的屬性,在這種方案里面,必然會導(dǎo)致line-height、font-size被繼承,因此在需要排版子容器時,需要復(fù)寫line-height、font-size。
2.2 子容器所在的line-box的line-height=父容器的height對上面的方法不兼容IE67且不能做到父容器自適應(yīng)的方面,可以這樣改進(jìn):
把子容器當(dāng)成行內(nèi)元素呈遞
構(gòu)建一個行內(nèi)級別的鉤子元素,緊挨著子容器,以使用:before/:after偽元素自制一個文本節(jié)點、或或任意一個inline級別的標(biāo)簽、或者一個1*1的圖片。
讓鉤子元素?fù)螡M容器高度,這意味著它需要成為inline-box元素,然后設(shè)置height:100%即可。
現(xiàn)在,子容器所在的 line-box 的 line-height = 父容器的 height。
最后,給子容器和鉤子元素設(shè)置vertical-align:middle,讓它們的中心線對齊于于父容器的middle-line,就能做到垂直居中。
http://jsfiddle.net/humphry/86dsC/21/
現(xiàn)在這個布局可以自動生成,詳見@林小志的css小工具:圖片垂直居中span。
(如果需要水平居中,那么這個額外的節(jié)點,需要移去自身所占的距離,一般使用margin-left:-1px或margin-right:-1px,取決于鉤子在子容器的哪一邊。)
說明:
兼容性:沒有涉及relative和absolute定位,布局時相對無痛。
兼容性:inline-box標(biāo)簽之間的任意數(shù)量的空白符:ASCII 空格 ( )、ASCII 制表符 ( )、ASCII 換頁符 ()、零寬度空格 () 會被瀏覽器解析成一個空格,造成間隙。需要通過改變HTML結(jié)構(gòu)/使用負(fù)margin等來去掉這個間隙。
兼容性:這個方案有一定hack量,去掉inline-box的空格間隙是一部分,display:inline-block的IE67 hack是另一部分。
自適應(yīng):父容器可以自適應(yīng)于外部了,因為這里不需要在任何地方知道父容器的高度。
溢出:子容器溢出時會變成頂對齊,原因同上。
3. 普通流,塊級table布局 (css2.1)方案 | 兼容性 | 父容器 | 子容器 | 子容器溢出 | 其他 | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|
IE8 | IE6/7 | 定高 | 自適應(yīng)于內(nèi)部 | 自適應(yīng)于外部 | 定高 | 自適應(yīng)于內(nèi)部 | 自適應(yīng)于外部 | 撐高 | 被截斷 | 不需手工計算 | |
父容器display:table-cell,子容器vertical-align | √ | × | √ | × | × | √ | √ | √ | √ | × | √ |
子容器被table、tr、td包裹 | √ | √ | √ | √* | √* | √ | √ | √ | √ | × | √ |
這個方案依然是用到vertical-align:middle,只不過需要放到作為display:table-cell的元素之上。
http://jsfiddle.net/humphry/7AMF9/2/
這個布局也可以自動化生成:見@林小志的css小工具:圖片垂直居中 table cell
說明:
兼容性:IE6/7不兼容display:table-cell。
自適應(yīng):子容器無法自適應(yīng)于父容器,高度無法使用百分比單位,因為根據(jù)渲染規(guī)則,display:table-cell的元素的包含塊是它父級的display:table的元素。
溢出:父元素就算給定高度,設(shè)置overflow,也不會導(dǎo)致溢出隱藏;在子元素溢出的時候,父容器不能保有自身設(shè)置的高度,直接會被撐高。
其他:display:tabel-cell本身讓很多屬性無效。
3.2. 子容器被table、tr、td包裹為了可以讓子容器有百分比高度,我們可以直接構(gòu)建一個表結(jié)構(gòu)出來:
http://jsfiddle.net/humphry/Ns4RK/8/
說明:
兼容性:這是一個全兼容的方案。
自適應(yīng):現(xiàn)在“父級”的自適應(yīng)要求都可以得到滿足,只不過這里的“父級”指的是包在最外層的table。
溢出:父元素就算給定高度,設(shè)置overflow,也不會導(dǎo)致溢出隱藏。
其他:文檔結(jié)構(gòu)變復(fù)雜了,語義被拋棄了。
其他:display:tabel-cell本身讓很多屬性無效。
其他:可以把這個方案里的 這是互聯(lián)網(wǎng)上能找到的最多的關(guān)于垂直居中的方法。我們不相信瀏覽器,使用手算,將子元素挪去自身高度的50%。 說明: 兼容性:子元素和父元素都需要設(shè)置position,這就意味著IE67下面的數(shù)十個友情附贈的美好bug。 自適應(yīng):子元素必須定高,不定高算不出來負(fù)margin。不可以是百分比高度單位,因為margin-top的百分比,是相對其包含塊的寬度而言的。 自適應(yīng):父容器可以自適應(yīng)于內(nèi)部,只不過不是這個子元素,而是父容器內(nèi)部其他的元素。子元素對外層高度、寬度塌陷,不能撐寬/撐高父容器了。 溢出:這個方案也可以支持子元素高度溢出的情形。 其他:需要手動計算子元素1/2的高度是多少。 這個的原理寫在CSS2.1中: ‘top’ + ‘margin-top’ + ‘border-top-width’ + ‘padding-top’ + ‘height’ + ‘padding-bottom’ + ‘border-bottom-width’ + ‘margin-bottom’ + ‘bottom’ = 包含塊的高度 在其他值不是auto的時候,margin-top和margin-bottom是可以根據(jù)上式算出的,原理類似于水平居中。 說明: 兼容性:這個方案僅僅支持IE8+。IE6和IE7由于對同時定義top、bottom屬性的樣式解析與 css2.1 不一致,不支持這種定位方式。 自適應(yīng):父容器可以自適應(yīng)于內(nèi)部,只不過不是這個子元素,而是父容器內(nèi)部其他的元素。原因同上。 自適應(yīng):這個方案需要子容器有一個固定的高,或百分比自適應(yīng)于外部。它的高度不能是height:auto,因為這樣會使得上面的算式里auto出現(xiàn)在三個地方,瀏覽器無法計算出相應(yīng)margin值。 溢出:這個方案也可以支持子元素高度溢出的情形。 其他:完全不用算,耶! 原理同上,僅僅是僅僅是用translate替換了負(fù)margin,因為translate的百分比偏移量是容器本身的。 說明: 兼容性:ie9+(但,從好處來講,其實這個兼容性已經(jīng)完全不需要考慮IE6~8的相對/絕對布局bug了) 自適應(yīng):子元素可以不指定高度,也可以相對父級高寬做百分比設(shè)置,也包括定寬,非常靈活 自適應(yīng):父容器可以自適應(yīng)于內(nèi)部,只不過不是這個子元素,而是父容器內(nèi)部其他的元素。原因同上。 溢出:支持子元素溢出隱藏,或者溢出顯示。 其他:你會讓代碼陷入一個前綴的海洋…… 說明: 兼容性:只能是IE9+和現(xiàn)代瀏覽器 自適應(yīng):背景可以任意自適應(yīng)于外部容器,或者定高寬。也可以讓子容器自適應(yīng)于內(nèi)部內(nèi)容,背景自適應(yīng)于子容器。 溢出:支持背景溢出隱藏,但無法溢出顯示。好消息是,可以使用background-clip指定背景從哪里消失。 其他:你甚至可以把.inner的標(biāo)簽省掉,直接把背景放到.outer之上 說明: 兼容性:只能是IE9+和現(xiàn)代瀏覽器 其他:兼容性是我目前已知的東西…… 文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。 轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/110848.html 摘要:效果圖為了讓效果更明顯,特意設(shè)置了兩邊字體大小不同關(guān)鍵代碼父容器子容器這里要提一下的是,只對于內(nèi)聯(lián)元素或者內(nèi)聯(lián)內(nèi)容有效,比如說為塊級元素標(biāo)簽設(shè)置行高,實際上是為標(biāo)簽中的內(nèi)聯(lián)文字設(shè)置了行高。允許指定負(fù)長度值和百分比值。
前言
先扯一段廢話來引入好了。又很久沒有寫文章了(間接性躊躇滿志,持續(xù)性混吃等死),幾個月了登上來看到有人收藏和點贊,感到很慚愧,最近主要精力花費在react和redux... 摘要:為了更好的加深對居中的理解,搜集和閱讀相關(guān)資料,發(fā)現(xiàn)不錯的文章將其整理出來。
在學(xué)習(xí)前端的過程中,發(fā)現(xiàn)元素和文本的水平居中和垂直居中,是經(jīng)常會出現(xiàn)的問題,在實際工作中也會經(jīng)常碰到。居中的技巧有很多,但在編寫代碼的過程中,發(fā)現(xiàn)有時候技巧管用,有時候不管用,于是就將每個知道的方案都試一遍,找到合適的。這種情況究其原因是對居中的認(rèn)識不夠深入,只是停留在實現(xiàn)需求的水平上。為了更好的加深對居中的... 摘要:用來控制表格單元格寬度你也許遇到過給表格設(shè)置了寬度,但是不起作用的問題。這是因為單元格的寬度是根據(jù)其內(nèi)容進(jìn)行調(diào)整的。顯而易見的,默認(rèn)情況下,單元格寬度受其內(nèi)容約束。而設(shè)置了后,其單元格寬度變得可控了。
本文首發(fā)于我的博客在上文《你不知道的CSS(一)》中,介紹了兄弟選擇器美化表單,font-size:0消除間隙,overflow清除浮動,border繪制三角形等7個實用技巧。由于文章長... 摘要:前言屆校招陸陸續(xù)續(xù)開始了,整理了一些高頻的面試題。標(biāo)簽提供給頁面的一些元信息名稱值對,有助于。開啟缺點一個是不支持,另一個是一旦子元素的大小超過父容器的大小,就會出顯示問題。用于設(shè)置或檢索元素的縮放比例,值為即使用元素的實際尺寸。
前言
2019屆校招陸陸續(xù)續(xù)開始了,整理了一些高頻的面試題。
HTML部分
1. 什么是?
DOCTYPE是html5標(biāo)準(zhǔn)網(wǎng)頁聲明,且必須聲明在HTML文檔...換成display:table的其他元素,tr、td亦然:
http://jsfiddle.net/humphry/KxKc8/
個人覺得……徒增煩惱爾。
4. 絕對定位布局 (css2.1)
4.1 子容器絕對定位,top:50%,負(fù)margin
方案
兼容性
父容器
子容器
子容器溢出
其他
IE8
IE6/7
定高
自適應(yīng)于內(nèi)部
自適應(yīng)于外部
定高
自適應(yīng)于內(nèi)部
自適應(yīng)于外部
撐高
被截斷
不需手工計算
子容器絕對定位,top:50%,負(fù)margin
√
√
√
√*
√
√
×
×
×
√
×
子容器絕對定位,top:0,bottom:0,margin:auto
√
×
√
√*
√
√
×
√
×
√
√
.outer{ position: relative; }
.inner{ position: absolute; top: 50%; height: 20px; margin: -10px; }
.outer{ position: relative; }
.inner{ position: absolute; margin-top: auto; margin-bottom : auto;
top: 0; bottom: 0; height: 20px; }
5.1 子容器絕對定位,top:50%,translateY(-50%)
方案
兼容性
父容器
子容器
子容器溢出
其他
IE8
IE6/7
定高
自適應(yīng)于內(nèi)部
自適應(yīng)于外部
定高
自適應(yīng)于內(nèi)部
自適應(yīng)于外部
撐高
被截斷
不需手工計算
子容器絕對定位,top:50%,translateY(-50%)
×
×
√
√*
√
√
√
√
×
√
√
backgournd代圖片backgournd-size
×
×
√
√
√
√
√*
√
×
√
√
flexbox
×
×
.outer{ position: relative; }
.inner{ position: absolute; top: 50%; transform: translateY(-50%);}
.inner{
-webkit-transform:translate(-50%, -50%);
-moz-transform:translate(-50%, -50%);
-ms-transform:translate(-50%, -50%);
-o-tranform:translate(-50%, -50%);
transform:translate(-50%, -50%);
}
5.2 backgournd代圖片,backgournd-size
.inner{ background-image: url("...") ; background-size: cover ; height: 100% ; }
// TBD
// 很抱歉,由于對flexbox沒有深入的了解,我還沒有試驗出flexbox在子元素溢出時也能保持居中的解決方案……最好的結(jié)果是子元素被拉伸(= =)。有人有過實例嗎?
相關(guān)文章
css常用技巧整理-布局綜述篇
對css居中的一點總結(jié)
你不知道的CSS(二)
2019屆校招前端面試題整理——HTML、CSS篇
發(fā)表評論
0條評論