CSS奇技淫巧之負邊距的應用

最近在學習flex布局,在贊嘆其便捷性的同時,回想起之前使用css2的時候實現等高或者等寬布局的麻煩。同時也看到[The Definitive Guide to Using Negative Margins這篇文章對于負邊距的介紹,這里參考并總結一二,加深理解。

我們在平時的開發中很少使用負邊距,不過其實可以解決很多問題。首先,W3C標準并不反對使用負邊距,此外,使用負邊距時并不會時節點脫離文檔流,因此能夠影響后繼節點的布局,此外,它也有著較好的兼容性,在適當的時候合適的使用它可能解決大問題。

我們先借用參考文章里的一張圖來回顧一下盒模型:


盒模型.png

仔細看圖中的箭頭所示,對一個非float元素來說,top,left屬性影響元素本身的定位,而right,bottom影響的是后繼元素的定位。理解這點其實很重要,很多時候我們會覺得很奇怪,明明設置了margin-bottom為0,可是為什么沒有相對父元素居于底部呢。

一個有趣的現象是,當我們并未對節點設置寬度,但是設置了負的margin-left或者margin-right時,會導致節點變寬,其效果有點類似padding。

而對于float節點,負的margin稍顯復雜,我們不妨先看看float方向和負邊距方向相反的情形:

#mydiv1 {
    float:left; 
    margin-right:-100px;
}

而HTML結構為

<div id="mydiv1">First</div>
<div id="mydiv2">Second</div>

我們使用codepen來查看上述結果,不難發現,mydiv2由于負值margin-right的重疊作用,直接覆蓋mydiv1.當我們把mydiv1設置成寬度100%時,便輕松實現了mydiv2固定寬度,而mydiv1占寬100%的布局,而不需使用position:absolute.

當mydiv1和mydiv2都被設置了margin-right為-20px時,其效果是mydiv1的寬度減少了20px,因為被mydiv2覆蓋的緣故。

不難想象,當mydiv1的負margin-right設置的值超過其寬度時,則完全被覆蓋。

這里可以思考一下,假設頁面布局如下:

<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會否覆蓋到mydiv呢?

再看一個例子,要把單列的列表改成多列混排,繼續盜圖:

多列布局.png

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 */

如此,便順利的從單列布局轉為多列布局。初看這部分代碼時,我也覺得很奇怪,怎么第4個和第6個li標簽無需設置margin-top就可以實現節點上移而實現多個塊元素相互重疊的效果?這里必須提到的一點是,負值的margin-top會導致文檔流上移,想明白了這一點,就不難理解這里的布局為何是這樣了。關于margin的更深入的討論,我會在參考文獻中列出。

負值的margin還有其他應用,比如氣泡文字,文本疊加效果等,再也不用使用死板的絕對定位了。

氣泡提示文字.png

當然,要實現多列布局也很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設置margin-right很重要,因為content的實際寬度仍然是100%,否則會導致p標簽和sidebar重疊。

使用負的margin-top可能會導致一系列問題,比如選擇和點擊頁面元素,由于節點相互重疊可能導致層級不符合預期,解決方法也很簡單,使用position:relative即可!

最后,再回顧一下經典的等高布局代碼:

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>

這里主要用到的原理是:

  • 未設置父節點高度時,其高度由高度最高的子節點高度決定
  • 負值的margin-bottom可以減少父節點高度,對子節點高度不影響,也不影響子節點定位

關于margin,其實還有很多值得去深挖的東西,比如當沒有設置padding和border時,子節點和父節點的margin-to會重疊;而兩個平級的節點之間的margin-bottom和margin-top之間也會重疊,在你不知道的CSS——BFC(塊級格式化上下文)中,我們會對此進行詳細解釋。

參考文獻:
你不知道的CSS——BFC(塊級格式化上下文)
The Definitive Guide to Using Negative Margins
Html+CSS__margin 負值之美:負margin在頁面布局中的應用
深入理解margin重疊以及負margin對元素大小的影響
不要告訴我你懂margin
由淺入深漫談margin屬性

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽默認的外補...
    _Yfling閱讀 13,786評論 1 92
  • relative:生成相對定位的元素,通過top,bottom,left,right的位置相對于其正常位置進行定位...
    zx9426閱讀 963評論 0 2
  • CSS布局奇淫巧計之-強大的負邊距css中的負邊距(negative margin)是布局中的一個常用技巧,只要運...
    呦泥酷閱讀 460評論 0 1
  • 我喜歡一種泥土 它叫鄉土 對,是生活在鄉村的泥土 我喜歡把萬物比做生命 而我會在里面尋找它的溫度與厚度 鄉土就是我...
    秋二生閱讀 190評論 0 0
  • 活的沒有自我的時間,雖然我也愛你,可是我還是我,我也要有我的自由時間
    里鯊閱讀 370評論 0 0