margin系列之內(nèi)秀篇

2018-02-24 15:22 更新

margin系列之內(nèi)秀篇

原作者:doyoe
原文鏈接:http://blog.doyoe.com/2013/12/06/css/margin%E7%B3%BB%E5%88%97%E4%B9%8B%E5%86%85%E7%A7%80%E7%AF%87/

最Cool的利器

一樣?xùn)|西在不同的場(chǎng)景,不同的人手里,所能做的事會(huì)有很大不同。我深切的以為 margin 絕對(duì)是 CSS 中最有能力的利器之一,不知大家以為然否?

前面幾篇文章大概的講了一些關(guān)于 margin 的特性,所以本篇會(huì)聊聊 margin 的實(shí)際應(yīng)用場(chǎng)景,也算讓自己休息一下,不用再講知識(shí)點(diǎn)。

有個(gè)很典型的需求

相信接下來(lái)這個(gè)需求,你十有八九實(shí)現(xiàn)過(guò),甚至實(shí)現(xiàn)過(guò)多次,來(lái)看 圖一

我們看到這個(gè)圖中,有個(gè)列表,每個(gè)列表項(xiàng)下面都有一條線,但最后一項(xiàng)沒(méi)有。我們預(yù)期的代碼是:

<div id="demo">
    <h3>標(biāo)題列表</h3>
    <ul>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
    </ul>
</div>

如果每項(xiàng)都有條底線,我們可以很簡(jiǎn)單的做到,如下:

#demo li{
    border-bottom: 1px solid #ccc;
}

然而為了處理最后一項(xiàng),事情就變得有點(diǎn)糾結(jié)了。我知道肯定有人要說(shuō),我們有 :first-child, :nth-last-child(n), :nth-last-of-type(n) 之類(lèi)的CSS3選擇符,要處理這個(gè),太easy了。恩,我也不得不承認(rèn),CSS3確認(rèn)讓事情變得簡(jiǎn)單多了。但我們可能需要面對(duì)一些國(guó)情,因?yàn)樾枰疹櫼恍┤跣≌?,比如IE6-8,它們離CSS3的世界太遠(yuǎn)。

傳說(shuō)中的first/last解決方案

所以我們需要找別的方法,于是這樣的代碼,相信你見(jiàn)過(guò)無(wú)數(shù)遍了:

<div id="demo">
    <h3>標(biāo)題列表</h3>
    <ul>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
        <li>&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
        <li class="last">&raquo; 有點(diǎn)累想歇一下好長(zhǎng)一個(gè)標(biāo)題</li>
    </ul>
</div>

我沒(méi)亂說(shuō),你肯定見(jiàn)到類(lèi)似的代碼千百遍了?是的,它確實(shí)能夠解決我們的問(wèn)題,請(qǐng)看 DEMO1 傳說(shuō)中的first/last解決方案,代碼如下:

#demo .last{
    border-bottom: 0 none;
}

使用特殊的class來(lái)單獨(dú)處理這項(xiàng),但我不是很喜歡這樣的code,原因大致有:

  • 需單獨(dú)定義一個(gè)差異化的class;
  • 不利于數(shù)據(jù)循環(huán)輸出,因?yàn)檫€得判斷是否最后一項(xiàng);

margin的神來(lái)之筆

基于以上的原因,肯定會(huì)有其它的解決方案出現(xiàn),這時(shí)margin無(wú)疑是非常不錯(cuò)的選擇,來(lái)看代碼:

#demo{
    overflow:hidden;
}
#demo ul{
    margin-bottom: -1px;
}

CSS代碼如上,HTML代碼當(dāng)時(shí)使用開(kāi)篇時(shí)的那段,結(jié)果請(qǐng)看:DEMO2 margin解決方案

是不是很Cool,完全避免了上述的問(wèn)題,并且代碼量很小。至于為什么可以這樣實(shí)現(xiàn),前幾篇文章里有說(shuō)過(guò),margin是互動(dòng)的,能影響其上下文的布局。本例中,當(dāng) ul margin-bottom:-1px ,其本身的高并不會(huì)被改變,但其相鄰的元素則會(huì)往上 1px ,這時(shí)相鄰的元素即其包含塊 #demo,所以給 #demo overflow:hidden ,就直接將那 1px 的邊框給裁剪掉了。
再來(lái)個(gè)相似的需求

看看下述的 圖二,這應(yīng)該也是一種非常常見(jiàn)的圖片列表需求:

只關(guān)注圖片之間的間隙,我們發(fā)現(xiàn)3張圖片,卻只有2個(gè)間隙。不論你是用 margin-left 或者說(shuō)是 margin-right ,都無(wú)法直接達(dá)成這個(gè)需求。
當(dāng)然,可以像 DEMO1 那樣給第一個(gè)或者最后一個(gè)添加一個(gè)特殊類(lèi) first/last 來(lái)解決。但這種方式剛被說(shuō)不喜歡,所以想想用 margin 方式吧,思路應(yīng)該說(shuō)是和 DEMO2 毫無(wú)二致。來(lái)看代碼:

CSS

#demo{
    overflow:hidden;
}
#demo ul{
    margin-right:-10px;
}

HTML

<div id="demo">
    <h3>圖片列表</h3>
    <ul>
        <li><img src="https://atts.w3cschool.cn/attachments/image/cimg/1.jpg" alt="" /></li>
        <li><img src="https://atts.w3cschool.cn/attachments/image/cimg/2.jpg" alt="" /></li>
        <li><img src="https://atts.w3cschool.cn/attachments/image/cimg/1.jpg" alt="" /></li>
    </ul>
</div>

恩,就這么簡(jiǎn)單,很美妙。效果可移步 DEMO3 margin處理圖片列表間隙解決方案

我知道不少人還會(huì)使用給圖片列表容器加寬度的方式來(lái)進(jìn)行處理,當(dāng)然,它很OK,不過(guò)不夠靈活,因?yàn)樵诓煌瑘?chǎng)景下,寬度可能不一樣,這樣的code無(wú)法被提取為公用樣式,復(fù)用性不強(qiáng)。

margin 的方式完全不care幾乎任何場(chǎng)景,都可以使用,因?yàn)樵诖蠖鄶?shù)情況,我們這樣一個(gè)圖片模塊都是自適應(yīng)寬度的,因?yàn)樗鼤?huì)處于某個(gè)layout下,寬度完全取決于layout,所以其實(shí)在真實(shí)場(chǎng)景下 #demooverflow 并不是必須的,也就是說(shuō) margin-right 的負(fù)值理論上可以預(yù)設(shè)成一個(gè)很大的值。

CSS

#demo ul{
    margin-right:-100px; /* 這個(gè)可以設(shè)置得比li的間隙更大,所以理論上可以寫(xiě)一次而適用于真實(shí)場(chǎng)景的任何情況 */
}

看我們簡(jiǎn)單還原的真實(shí)場(chǎng)景使用方式:DEMO4 模擬真實(shí)場(chǎng)景:margin處理圖片列表間隙解決方案。恩,就這樣,靈活性和可擴(kuò)展性爆棚,不是么?

縮進(jìn)實(shí)例

依然先貼個(gè)圖,以下是 圖三
文本縮進(jìn)

貌似是個(gè)好常見(jiàn)的需求場(chǎng)景,當(dāng)然,要實(shí)現(xiàn)這樣的效果,對(duì)于大家來(lái)說(shuō)都不過(guò)是信手拈來(lái),再容易不過(guò)。

HTML

<div>
    <strong>簡(jiǎn)介:</strong>
    <p>該寫(xiě)點(diǎn)什么好呢?好頭痛,一個(gè)能把value念成“哇柳”的中老年人,猛然覺(jué)得沒(méi)文化好可怕。</p>
</div>

你可能隨手就會(huì)寫(xiě)下 float + margin/padding,float + bfcabsolute + margin/padding,flex 等方案中的隨意一個(gè),恩,都很Cool,我也常這么干。

只是有的時(shí)候在一個(gè)小場(chǎng)景下,希望能比較輕量的出來(lái)這樣的縮進(jìn),可能不想有浮動(dòng),絕對(duì)定位,清除浮動(dòng)之類(lèi)的,怎么破?

margin依然是你很好的選擇

你想到了嗎?是的,用margin。

HTML

<p><strong>簡(jiǎn)介:</strong>該寫(xiě)點(diǎn)什么好呢?好頭痛,一個(gè)能把value念成“哇柳”的中老年人,猛然覺(jué)得沒(méi)文化好可怕。</p>

CSS

p{
    padding-left:45px;
}
strong{
    margin-left:-45px;
}

看起來(lái)很簡(jiǎn)單,沒(méi)有浮動(dòng),沒(méi)有絕對(duì)定位,沒(méi)有其它重布局,很清涼有木有?

甚至 HTML 也可以更簡(jiǎn)單,因?yàn)闊o(wú)需對(duì)后面那長(zhǎng)段做任何處理,所以不需要再加包裹。來(lái)看看具體例子吧。DEMO5 margin縮進(jìn)實(shí)例。我想這樣的輕量方式,在一定時(shí)候還是有使用價(jià)值的,不是么?

視覺(jué)欺騙偽等高

等高布局在一段時(shí)間內(nèi)好似挺火,方案也涌現(xiàn)過(guò)不少,如 圖四
等高布局

該圖要求,不論是主欄還是側(cè)欄,總是以最高的那列為基準(zhǔn)高度。核心代碼:

CSS

#doc{
    overflow:hidden;
}
#main,#aside{
    margin-bottom:-999px;
    padding-bottom:999px;
}

HTML

<div id="doc">
    <div id="main">主內(nèi)容欄<br />占位內(nèi)容</div>
    <div id="aside">側(cè)邊欄</div>
</div>

先看看結(jié)果:DEMO6 margin偽等高布局

效果和我們的要求一致,達(dá)到了等高布局。需要提醒的是,這其實(shí)只是視覺(jué)欺騙,做到的了偽高等高。主欄和側(cè)欄的實(shí)際高度其實(shí)并不相等,之所以可以達(dá)成這樣的效果,其原因在于負(fù) margin 值。我們前文中有提到過(guò),margin 會(huì)影響其上下文布局,當(dāng)我們將 margin-bottom 設(shè)置為負(fù)值時(shí),其相鄰的包含塊元素,底部會(huì)自動(dòng)上去其負(fù)值的高度,直到最高的那列底部邊緣為止,然后裁剪。但該列本身的高度并不會(huì)發(fā)生變化,同時(shí)因?yàn)橛?padding-bottom 向下擴(kuò)展,顏色被填充滿padding區(qū)域,于是達(dá)到視覺(jué)上的等高。
描述的貌似有點(diǎn)復(fù)雜,沒(méi)文化好可怕。差不多就這樣,不能接著往下寫(xiě)了,要不收不住。

作為 CSS 的重要屬性 margin 有很多可被挖掘的潛力,需要更多的是想法。enjoy it.

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)