CSS中的負邊距

LeuisKen發表於2016-07-02

2015-04-22 時候寫的老文,因為希望引用所以拿了出來。

那天被一個同學問了一個問題,三列的div,要求父div的高度和三個div的高度都和三個中字數最多,也就是高度最高的那個一樣高。試了試才發現確實有問題。在網上查到了解決方案,運用了一些很奇葩的程式碼,貼上來和大家分享。點選這裡檢視demo

之後仔細的百度了一下,發現了這麼一個叫做內外補丁負值法的東西。不過百度內外補丁負值法,出來的都是同一篇文章,感覺不是一個真正的術語。還是把這篇文章貼出來,有興趣的同學可以看看。

在這個解決方案中,又涉及到了傳說中的負margin。之前在阿里筆試也有一個三欄佈局的題,其中一個解決方案用的也是左右的負margin。深入研究之後又發現了聖盃佈局、雙飛翼佈局等很多示例,確實要好好研究負邊距這個東西了。

之後參考了CSS佈局奇淫巧計之-強大的負邊距這篇文章,裡面做了實際的demo,總結成一點就是,css中盒子真正的邊界,是由margin決定的,而且margin可以很霸氣的通過負值來壓縮實際寬度(padding不允許負值)。

有了這一點認識之後,很多問題都解決了。就比如說上邊那個demo,通過padding-bottom:10000px;建立了一個足夠高的盒子,再通過margin-bottom:-10000px;抵消這部分盒子在文件流中的實際佔位(但是實際還是存在的,所以就會按照第一個的高度等高),再給父級元素加上overflow:hidden,去掉多餘的高度,效果就實現了。

同時,在上邊那篇文章裡還解決了一個佈局的問題,就是多列間有margin,但是兩邊沒margin的問題(聽不懂我中文的直接點這裡看demo吧,我知道自己說的不好)。之前一直是迴圈到一行最後一個的時候給加上一個class,現在可以免了,就比如我在demo裡用margin-right:10px;給li之間建立一個間隔,然後用marigin-rignt:-10px;強行加寬ul,使四個li能在一行,但是ul外content的寬度設為width:830px;(4200px+310px;),這樣就可以正確的居中了。

之後簡單說下聖盃佈局和雙飛翼佈局吧,他們主要是為了解決三欄問題。三欄問題的研究可以看看張鑫旭老師的部落格文章我熟知的三種三欄網頁自適應的佈局方法。然後以雙飛翼舉例吧,他的DOM結構是這樣的。

    <div class="main">
        <div class="main-content"></div>
    </div>
    <div class="sub"></div>
    <div class="extra"></div>

把main放在最前面,然後對.sub(也就是left)使用margin-left:100%;強行移動到左邊;對.extra(也就是right)使用margin-left:(right的寬度);強行移動到右邊。由於右邊的欄會蓋住main的內容,所有就直接給main里加上子div,通過給子div加上margin-right防止重疊保證正常顯示。如此煞費苦心的佈局目的只有一個,就是讓瀏覽器先渲染main,實現主內容先被載入的效果。聖盃佈局的話,印象中就是把.main-contentmargin換成了.mainpadding,目的都是一樣的。

再多說一點關於三欄佈局的東西,就是在利用浮動佈局來實現三欄的時候,應該記住,在DOM裡的順序,是左浮動的div最前,右浮動的div中間,中間的在最後,不然就會出問題。千萬不要想當然覺得中間的div在DOM的中間,然後兩邊div分別float。因為中間的div預設要佔一行,按理說右邊的會先被擠下去,再float,所以他就上不來了,實現不了我們想要的效果。如果沒有把中間的div放到第一個位置的需求的話,還是建議用浮動的方法做三欄佈局,簡單易用成本低。

自此也算是總結了負邊距的一些效果,有時候想想的話,要是pading支援負值的話又會有什麼樣的奇怪方案出現呢?

== 2015-11-27更新 ==

今天見到了一個奇怪的面試題,用三個div實現一條彩虹,同樣使用了負邊距。

相關推薦:

相關文章