看了這篇文章,你可以了解到以下布局方法:
table-cell
定高水平垂直居中
不定高水平垂直居中
單行定高水平垂直居中
單行不定高水平垂直居中
多行定高水平垂直居中
多行不定高水平垂直居中
多列等高布局
左邊定寬右邊自適應(yīng)布局
左邊右邊定寬中間自適應(yīng)三列布局
最近開(kāi)發(fā)遇到一些布局上的問(wèn)題,由于不確定因素比較多,比如不定寬高、單行多行的情況需要顯示的樣式基本相同。這樣的情況會(huì)比較復(fù)雜,后來(lái)找到display:table-cell這個(gè)布局神器,這些問(wèn)題也就不是問(wèn)題了。比如以下這種情況:
基于這樣的需求,我們通常都是每一種情況需要單獨(dú)的寫(xiě)一份hack樣式,這樣寫(xiě)起來(lái)很麻煩。我們多么希望寫(xiě)一份樣式,不管你里面的節(jié)點(diǎn)如何變,定不定寬高,多行與否都能表現(xiàn)一致。針對(duì)水平|垂直居中的情況,我找到了table-cell布局的方式,基本能解決。下面會(huì)總結(jié)一下table-cell的布局原理以及列舉一些日常布局所遇到的情況。
1、table的一些特性與表現(xiàn)形式
雖然table布局因?yàn)樗囊恍┓钦Z(yǔ)義化、布局代碼冗余,以及不好維護(hù)改版等缺點(diǎn)被趕出了布局界。但是在css不給力時(shí)期,table布局也曾風(fēng)靡一時(shí),就算現(xiàn)在看來(lái)table的一些布局的特性也是非常給力的,而幸好css也吸取了table布局一些好的特性為己用。讓我們可以使用更少、更語(yǔ)義化的標(biāo)簽來(lái)模擬table布局,可以跳過(guò)table布局的缺點(diǎn)又實(shí)現(xiàn)我們想要的效果,所以我們首先需要了解table的一些特性以及對(duì)應(yīng)的css屬性。
我們?cè)诓痪又惺褂玫降囊簿褪莟able、tr、td的一些特性,所以我們只需要了解這三個(gè)標(biāo)簽的特性就足夠了。
table標(biāo)簽(display:table)
1) table可設(shè)置寬高、margin、border、padding等屬性。屬性值的單位可以使用px,百分比值。
2) table的寬度默認(rèn)由內(nèi)容的寬高撐開(kāi),如果table設(shè)置了寬度,寬度默認(rèn)被它里面的td平均分,如果給某一個(gè)td設(shè)置寬度,那么table剩余的寬度會(huì)被其他的td平均分(有點(diǎn)類(lèi)似flex布局)
3) 給table設(shè)置的高度起到的作用只是min-height的作用,當(dāng)內(nèi)容的高度高于設(shè)置的高度時(shí),table的高度會(huì)被撐高。
tr標(biāo)簽(display:table-row)
1) 給tr設(shè)置高度只起到min-height的作用,默認(rèn)會(huì)平分table的高度。
2) tr中的td默認(rèn)高度會(huì)繼承tr的高度,若給任一td設(shè)置了高度,其他td的高度也同樣變高。適合多列等高布局
3) 設(shè)置寬度、margin、都不起作用
td標(biāo)簽(display:table-cell)
1) td默認(rèn)繼承table的高度,且平分table的寬度
2) 若table(display:table)不存在,給td設(shè)置的寬高不能用百分比只能用準(zhǔn)確的數(shù)值
3) 給td設(shè)置vertical-align: middle; td元素里面(除float、position:absolute)所有的塊級(jí)、非塊級(jí)元素都會(huì)相對(duì)于td垂直居中
4) 給td設(shè)置text-align: center; td元素里面所有非block元素(除float、position:absolute)都會(huì)相對(duì)于td水平居中,雖然block元素不居中,但其中的文字或inline元素會(huì)水平居中
了解了table的一些屬性,當(dāng)我們遇到一些水平垂直居中的布局時(shí),就會(huì)變得so easy了。
2、圖片定高|不定高水平垂直居中
圖片本身就是inline-block元素,那么我們只要給它的父級(jí)元素加個(gè)display:table-cell就好了
.box{ height: 200px; width: 200px; display: table-cell; text-align: center; border: 1px solid #ccc; vertical-align: middle; } <div class="box"> <img src="https://ss1.baidu.com/70cFfyinKgQFm2e88IuM_a/forum/pic/item/242dd42a2834349b406751a3ceea15ce36d3beb6.jpg"> </div>
就是那么簡(jiǎn)單。demo
3、多行定高|不定高|定寬|不定寬水平垂直居中
我們平時(shí)常見(jiàn)的就是單行水平垂直居中,其實(shí)就是簡(jiǎn)單的text-align:center; 然后再是line-height:xx 就搞定了。但是多行的就相對(duì)于復(fù)雜點(diǎn)。但是使用了table-cell之后,就變得很簡(jiǎn)單了
當(dāng)然,里面也可以是多個(gè)標(biāo)簽形成的多行,然后進(jìn)行水平垂直居中
demo1 demo2
其實(shí)實(shí)現(xiàn)的原理還是使用table-cell,先把外層box設(shè)置為table-cell,再把里面的元素設(shè)置為inline|inline-block(不定寬高|元素居中)或者block(寬度100%|文字居中)那么就可以控制里面的元素水平垂直居中了。基于這樣的布局方式,你就可以把什么定高|不定高|定寬|不定寬|多行|單行的水平垂直居中都搞定了。
4、左右浮動(dòng)元素垂直居中
由于display:table-cell對(duì)浮動(dòng)元素是不起作用的,當(dāng)我們需要兩個(gè)元素一個(gè)左浮動(dòng)一個(gè)右浮動(dòng),并且這連個(gè)元素還居中的時(shí)候。上面的方法就不起作用了。那我們可以換個(gè)法子,既然display:table-cell;的垂直居中不能直接對(duì)浮動(dòng)元素起作用,那就來(lái)個(gè)間接的嘛。給兩個(gè)浮動(dòng)的元素外面一個(gè)display:inline-block;的元素,并且清除浮動(dòng)。然后讓display:table-cell的垂直居中對(duì)inline-block元素起作用就好了。demo
如果你的需求還需要在兩個(gè)浮動(dòng)的元素中再添加水平垂直居中的話(huà),那么同樣的道理,只需要在這兩個(gè)元素中構(gòu)造符合table-cell布局的結(jié)構(gòu)就好了。
5、一行多列水平垂直居中
經(jīng)常會(huì)有這樣的需求,一列里面可能會(huì)有1、2、3個(gè)子元素,不管幾個(gè)都是要居中的。有了table-cell就可以輕松解決了。
實(shí)現(xiàn)原理也基本是把外層box設(shè)置為display:table-cell;然后設(shè)置居中。里面的元素item設(shè)置成inline或者line-block;就可以了,不管里面的item的個(gè)數(shù)多少,都會(huì)居中的,包括item是圖片也會(huì)這樣。[demo]()
本人測(cè)試:
6、多列等高布局
有這樣的需求,一行有三個(gè)item,三個(gè)item的高度不定,但是這一行的三個(gè)item最終的高度以最高的那個(gè)為準(zhǔn)。按照以前的做法要不就是砍掉需求,必須定高。實(shí)在不行就是等加載完之后用js計(jì)算三個(gè)item的高度,然后把最高的高度給其他item設(shè)置高度。這樣有點(diǎn)惡心,并且會(huì)出現(xiàn)抖動(dòng)。有了table-cell之后,這個(gè)就不成問(wèn)題了,因?yàn)樵谝粋€(gè)tr中,里面的td必須是等高的,而不管里面內(nèi)容的高度。demo
認(rèn)證看代碼你會(huì)發(fā)現(xiàn)跟我們平時(shí)的定高布局布局不一樣,每行外面必須得有一個(gè)ul來(lái)保證里面item的等高,并且里面還需要使用多余的li來(lái)控制間距。這樣做的原因是因?yàn)閠r里面的元素不會(huì)自動(dòng)換行,所以必須手動(dòng)換行,給外面加個(gè)ul,(說(shuō)好的tr呢?)是這樣的,被設(shè)置為display:table-cell的元素會(huì)跟相鄰的兄弟元素共同生成一個(gè)虛擬的table、tr把自己包起來(lái),誰(shuí)叫td只能包在table里面呢。但是你直接寫(xiě)td標(biāo)簽是不會(huì)產(chǎn)生這樣的效果的。而使用多余的li來(lái)控制間距是因?yàn)閠able-cell元素不認(rèn)識(shí)margin,所以只能這樣做了。
在生成機(jī)構(gòu)的時(shí)候就需要判斷什么時(shí)候該換行了,而不是像以前一樣在一個(gè)ul里面生成全部的li了
7、左邊定寬右邊自適應(yīng)
8、左邊右邊定寬中間自適應(yīng)三列布局
總結(jié):
使用table-cell還可以實(shí)現(xiàn)很多的布局,需要自己去發(fā)揮想象。總結(jié)下來(lái)也就需要記住幾點(diǎn),設(shè)置了display:table-cell的元素具有以下特性。
text-align、vertical-align等對(duì)齊屬性起作用,margin不起作用。寬高百分比值不起作用。
會(huì)生成虛擬的table、tr把自己包裹住,如果有相鄰的兄弟元素也被設(shè)置了table-cell,則會(huì)跟兄弟元素一起生成虛擬的table、tr把自己包裹住,并一行等高顯示
多個(gè)table-cell元素會(huì)占滿(mǎn)被設(shè)置了display: table的元素的寬度,如果一個(gè)元素被設(shè)置了寬度,那么其他剩余的table-cell元素會(huì)占滿(mǎn)剩下的寬度。當(dāng)然,如果只有一個(gè)table-cell元素,就算設(shè)置了寬度也會(huì)占滿(mǎn)table元素的寬度。
對(duì)設(shè)置了float、absolute的元素不起作用。且IE6、7不支持
這就是所謂的table布局大法。
display: inline-block
inline-block元素把自己變成特殊的inline元素,對(duì)于相鄰的元素來(lái)說(shuō)表現(xiàn)出inline的特點(diǎn),允許空格。對(duì)于內(nèi)部元素來(lái)說(shuō)表現(xiàn)出block元素的特點(diǎn),可以設(shè)置高度和寬度。
空格是兩個(gè)標(biāo)簽中存在換行符or制表符or空格符(其實(shí)就是縮進(jìn))的原因生產(chǎn)的,只需要給設(shè)置了inline-block屬性的父元素設(shè)置font-size:0,就可以使標(biāo)簽中的空格失去寬度