最近在學(xué)習(xí)flex布局,在贊嘆其便捷性的同時(shí)档悠,回想起之前使用css2的時(shí)候?qū)崿F(xiàn)等高或者等寬布局的麻煩。同時(shí)也看到[The Definitive Guide to Using Negative Margins這篇文章對(duì)于負(fù)邊距的介紹,這里參考并總結(jié)一二隆箩,加深理解。
我們?cè)谄綍r(shí)的開(kāi)發(fā)中很少使用負(fù)邊距羔杨,不過(guò)其實(shí)可以解決很多問(wèn)題捌臊。首先,W3C標(biāo)準(zhǔn)并不反對(duì)使用負(fù)邊距问畅,此外娃属,使用負(fù)邊距時(shí)并不會(huì)時(shí)節(jié)點(diǎn)脫離文檔流六荒,因此能夠影響后繼節(jié)點(diǎn)的布局,此外矾端,它也有著較好的兼容性掏击,在適當(dāng)?shù)臅r(shí)候合適的使用它可能解決大問(wèn)題。
我們先借用參考文章里的一張圖來(lái)回顧一下盒模型:
仔細(xì)看圖中的箭頭所示秩铆,對(duì)一個(gè)非float元素來(lái)說(shuō)砚亭,top,left屬性影響元素本身的定位,而right,bottom影響的是后繼元素的定位殴玛。理解這點(diǎn)其實(shí)很重要捅膘,很多時(shí)候我們會(huì)覺(jué)得很奇怪,明明設(shè)置了margin-bottom為0滚粟,可是為什么沒(méi)有相對(duì)父元素居于底部呢寻仗。
一個(gè)有趣的現(xiàn)象是,當(dāng)我們并未對(duì)節(jié)點(diǎn)設(shè)置寬度凡壤,但是設(shè)置了負(fù)的margin-left或者margin-right時(shí)署尤,會(huì)導(dǎo)致節(jié)點(diǎn)變寬,其效果有點(diǎn)類似padding亚侠。
而對(duì)于float節(jié)點(diǎn)曹体,負(fù)的margin稍顯復(fù)雜,我們不妨先看看float方向和負(fù)邊距方向相反的情形:
#mydiv1 {
float:left;
margin-right:-100px;
}
而HTML結(jié)構(gòu)為
<div id="mydiv1">First</div>
<div id="mydiv2">Second</div>
我們使用codepen來(lái)查看上述結(jié)果硝烂,不難發(fā)現(xiàn)箕别,mydiv2由于負(fù)值margin-right的重疊作用,直接覆蓋mydiv1.當(dāng)我們把mydiv1設(shè)置成寬度100%時(shí)滞谢,便輕松實(shí)現(xiàn)了mydiv2固定寬度串稀,而mydiv1占寬100%的布局,而不需使用position:absolute.
當(dāng)mydiv1和mydiv2都被設(shè)置了margin-right為-20px時(shí)狮杨,其效果是mydiv1的寬度減少了20px厨诸,因?yàn)楸籱ydiv2覆蓋的緣故。
不難想象禾酱,當(dāng)mydiv1的負(fù)margin-right設(shè)置的值超過(guò)其寬度時(shí)微酬,則完全被覆蓋。
這里可以思考一下颤陶,假設(shè)頁(yè)面布局如下:
<div id="mydiv">Start</div>
<div id="mydiv1">First</div>
<div id="mydiv2">Second</div>
而樣式如下:
#mydiv {
float: left;
}
#mydiv1 {
float:left;
margin-right:-200px;
}
#mydiv2 {
float: left;
margin-right: -20px;
}
那么mydiv2會(huì)否覆蓋到mydiv呢颗管?
再看一個(gè)例子,要把單列的列表改成多列混排滓走,繼續(xù)盜圖:
HTML如下:
<ul>
<li class="col1">Eggs</li>
<li class="col1">Ham<li>
<li class="col2 top">Bread<li>
<li class="col2">Butter<li>
<li class="col3 top">Flour<li>
<li class="col3">Cream</li>
</ul>
CSS如下:
ul {list-style:none;}
li {line-height:1.3em;}
.col2 {margin-left:100px;}
.col3 {margin-left:200px;}
.top {margin-top:-2.6em;} /* the clincher */
如此垦江,便順利的從單列布局轉(zhuǎn)為多列布局。初看這部分代碼時(shí)搅方,我也覺(jué)得很奇怪比吭,怎么第4個(gè)和第6個(gè)li標(biāo)簽無(wú)需設(shè)置margin-top就可以實(shí)現(xiàn)節(jié)點(diǎn)上移而實(shí)現(xiàn)多個(gè)塊元素相互重疊的效果绽族?這里必須提到的一點(diǎn)是,負(fù)值的margin-top會(huì)導(dǎo)致文檔流上移衩藤,想明白了這一點(diǎn)吧慢,就不難理解這里的布局為何是這樣了。關(guān)于margin的更深入的討論赏表,我會(huì)在參考文獻(xiàn)中列出检诗。
負(fù)值的margin還有其他應(yīng)用,比如氣泡文字瓢剿,文本疊加效果等逢慌,再也不用使用死板的絕對(duì)定位了。
當(dāng)然间狂,要實(shí)現(xiàn)多列布局也很easy:
HTML
<div id="content"> <p>Main content in here</p> </div>
<div id="sidebar"> <p>I’m the Sidebar! </p> </div>
CSS
#content {width:100%; float:left; margin-right:-200px;}
#sidebar {width:200px; float:left;}
#content p {margin-right:210px;}
這里給p設(shè)置margin-right很重要攻泼,因?yàn)閏ontent的實(shí)際寬度仍然是100%,否則會(huì)導(dǎo)致p標(biāo)簽和sidebar重疊鉴象。
使用負(fù)的margin-top可能會(huì)導(dǎo)致一系列問(wèn)題坠韩,比如選擇和點(diǎn)擊頁(yè)面元素,由于節(jié)點(diǎn)相互重疊可能導(dǎo)致層級(jí)不符合預(yù)期炼列,解決方法也很簡(jiǎn)單,使用position:relative即可音比!
最后俭尖,再回顧一下經(jīng)典的等高布局代碼:
CSS
.div {
width: 100px;
overflow: hidden;
}
.div1, .div2 {
padding-bottom: 200px;
margin-bottom: -200px;
float: left;
width: 50%;
word-wrap: break-word;
}
HTML
<div class="div">
<div class="div1">111111111111111111111111111</div>
<div class="div2">
22222222222sd豆腐干豆腐豆腐干豆腐干豆腐干豆腐
</div>
</div>
這里主要用到的原理是:
- 未設(shè)置父節(jié)點(diǎn)高度時(shí),其高度由高度最高的子節(jié)點(diǎn)高度決定
- 負(fù)值的margin-bottom可以減少父節(jié)點(diǎn)高度洞翩,對(duì)子節(jié)點(diǎn)高度不影響稽犁,也不影響子節(jié)點(diǎn)定位
關(guān)于margin,其實(shí)還有很多值得去深挖的東西骚亿,比如當(dāng)沒(méi)有設(shè)置padding和border時(shí)已亥,子節(jié)點(diǎn)和父節(jié)點(diǎn)的margin-to會(huì)重疊;而兩個(gè)平級(jí)的節(jié)點(diǎn)之間的margin-bottom和margin-top之間也會(huì)重疊来屠,在你不知道的CSS——BFC(塊級(jí)格式化上下文)中虑椎,我們會(huì)對(duì)此進(jìn)行詳細(xì)解釋。
參考文獻(xiàn):
你不知道的CSS——BFC(塊級(jí)格式化上下文)
The Definitive Guide to Using Negative Margins
Html+CSS__margin 負(fù)值之美:負(fù)margin在頁(yè)面布局中的應(yīng)用
深入理解margin重疊以及負(fù)margin對(duì)元素大小的影響
不要告訴我你懂margin
由淺入深漫談margin屬性