`

CSS 的 margin 很困難

阅读更多

转自:http://xxxxxly.in/posts/css-margin/ 对照原文加入了图片

toggle()及變數、calc、:match 之類,直至現在都沒有的 CSS 屬性、選擇器被提出・實行起來,CSS3、4都變得有趣起來了。
在老舊的 Android 瀏覽器以外,沒有 prefix 下使用 border-radiusbox-shadow 等等的情況也逐漸增多了。

可能現在的最新技術在將來會變成必要的功能也說不定,不過基本功也是很重要的。
像是 floatposition 之類,折騰 CSS 時總是會有幾個位置會瓶頸,今次挑了個我認為是當中最難的 margin 來寫。

不時會聽到「margin 的 bug 挺多的」。
不過隨著深入了解,也有可能把正常動作跟 bug 互相混淆的情況發生。
如果能正確理解 margin 的話,就能築起一個具效率性的結構。雖然敘述的只是很基本的內容,如果能讀一下的話我會很榮幸的。 ## 盒子模式 (box model) ##

在說明 margin 之前,首先有需要先認識盒子模式。
當運用 CSS 時,下圖也必須要理解一下。

在 CSS 指定 margin 之後,上面圖解裡有寫 margin 的部份,就可以輸入相應的值。

margin 的種類

margin 有著多種類的屬性,同時也可省略。

個別指定

  • margin-top
  • margin-bottom
  • margin-left
  • margin-right

省略

  • margin: 0;(上下左右)
  • margin: 0 0;(上下)(左右)
  • margin: 0 0 0;(上)(左右)(下)
  • margin: 0 0 0 0;(上)(右)(下)(左)

邏輯屬性

  • margin-start
  • margin-end
  • margin-before
  • margin-after

margin-top 等等應該已經司空見慣,我想應該會有人是第一次看見 margin-start。
margin-(start|end|before|after) 是要禁止書寫方向旋轉而被提出來的。

margin-top 是從畫面看到的物理方向。相對的,
margin-start 就變成邏輯方向。

當使用這個屬性時,同一 CSS 裡的橫向、直向書寫都能保持平滑的切換。(不過 IE8 等等瀏覽器不能實現。)

margin, auto 和 width 的關係

在 margin 上設值為 auto 的話,正常都會是 0。
不過,如果指定了寬度 (width) 的話,不管 margin 的左右哪一方被設成 auto 也好,都會自動算出指定的數值。

當瀏覽器的寬度是 600px 的情況下

div {  
    width:100px;   
    margin-left:auto;   
}

在上面的例子得出,因為瀏覽器寬度是 600px,所以 margin-left 會自動變成 500px。

 

margin 的中央配置

在指定了寬度、margin-left 和 margin-right 指定了 auto 的情況下,左右的 margin 會被等分,盒子就會被配置於中央了。

Negative Margin

把 margin 的數值指定成負值可以移動要素。
在把出了格局 (pattern) 以外的結構再重組時可以幫到很多忙。

例如,想把結構弄成像以下般的圖。

<style>
/* css reset */
ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* demo */
#list {
    margin: 0 auto;
    border: 1px solid #000;
    padding: 8px 8px 0;
    width: 488px;
}

ul {
    margin-right: -8px; /* 在這兒指定 Negative Margin */
    /* width: 496px; 新增:如果無視 IE6,7 的話此段可以刪除 */
    overflow: hidden;
}

li {
    float: left;
    margin: 0 8px 8px 0;
    width: 116px;
    height: 116px;
    background-color: #bbb;
}

</style>

<div id="list">
    <ul>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>

上面源碼的範例

使用 Negative Margin 將會擴大結構的寬度。
可是如果不能理解上面每一行源碼的意思,那還是不要多用它了。

margin 與 padding

不管是 margin 還是 padding 也好,都能給予空間。

<style type="text/css">
.margin {
    margin-bottom:10px;
}
.padding {
    padding-bottom:10px;
}
</style>

<div class="margin">aa</div>
<div class="margin">bb</div>

<div class="padding">aa</div>
<div class="padding">bb</div>

margin 和 padding 都能給予空間。 表面上一樣,實則內裡運作完全不同。

padding 能把背景色、柵格 (grid) 留白,可是 margin 是可以把要素的全部給予間隔。

margin 的相沖

作為 padding 所沒有的功能,margin 卻帶有相沖作用。
這種作用會令 margin 之間產生重疊效果,覺得「margin 真的很難用」的最大理由也許就是因為這個。

有時候在特定的情況下,會產生出相沖不起作用的微妙現象。
因為太過微妙,初學者可能會心想「這不是有 bug 麼?」,而且還是經常性。

可是理解到 margin 的相沖理論,比起指定 margin 的單一方向、或使用 padding 來說,利用 HTML, CSS 來清除的情況還要多。

<style type="text/css">
    .margin {
      margin:10px 0; /* 上下指定距離 1em */
    }
    .padding {
      padding:10px 0; /* 上下指定距離 1em */
    }
</style>

<div class="margin">aa</div>
<div class="margin">bb</div>

<div class="padding">aa</div>
<div class="padding">bb</div>

 

在 padding 的情況下,div 的間是 10px+10px=20px。
在 margin 相沖作用下,div 之間只有 10px。

要理解相沖現象,把屬性比喻成人的話可能會更容易明白。

  • width 是骨骼
  • height 是身高
  • border 是皮膚
  • padding 是脂肪
  • margin 是心臟的距離

脂肪是一個物理的距離。

假設與心臟的距離是指 margin 的話,那麼 A 先生和心臟的距離是 1。 但是 B 先生不這麼認為,他覺得是 3。 即使 A 先生在進行心臟收縮的運動,但是客觀來說他們兩位的心臟距離實際會是 3。

margin 相沖的數值

數值愈大,便不會被相沖。

<style type="text/css">
.a {
    margin:20px 0;
}
.b {
    margin:30px 0;
}
</style>

<div class="a">a</div>
<div class="b">b</div>

在上方例子中,原本 div 之間的距離會是 20px + 30px = 50px。但因為相沖作用,較小的數值會被消除。

子元素相沖

即使是子元素的狀態也好,當 margin 重疊時便會發生。

兩方都有設定 margin 屬性時,相沖現象便會發生。

<style type="text/css">
.parent{
    margin:10px 0;
}
.child {
    margin:30px 0;
}
</style>

<div class="parent">
    <div class="child">child</div>
</div>

子元素相沖的另一個例子

<style type="text/css">
.parent {
    margin:30px 0;
}
.child {
    margin:10px 0 40px;
}
</style>

<div class="parent">
    <div class="child">demo</div>
</div>

上面的例子指出,.parent 的 margin-top 屬性的值比較大所以最終它的值會是 30px。
可是 margin-bottom 的值是 .child 的比較大所以最終的值會是 40px。
在相沖現象發生時,數值愈大愈會被優先處理。這點要好好記住。

不會導致相沖現象出現的個案

當父元素被指定了某類特定的 CSS,子元素便不會與之相沖。

  • border (被 margin 指定了方向)
  • padding (被 margin 指定了方向)
  • overflow: hidden, scroll (auto, visible 值不適用)
  • position: absolute, fixed (relative, static 值不適用)

還有除了上述的例子外,根據 float 屬性也會有相沖不會發生的情況。

margin 和 float 的關係

margin 和 float 有著緊密的關係。
要純熟的使用 float,一定要對 margin 有所理解。

在指定了 margin 的元素時再指定 float 的情況下

不管是父或子元素,指定了 margin 之上再加入 float 屬性就會令相沖無效。

又像是記載了 width 和 margin: auto; 的關係一樣,當指定 width 和 margin 值時的 auto,會自動算出數值。
可是在這個情況下,如果有指定 float 的話,margin 中的 auto 數值必定歸 0。

指定 margin: auto; 和 float 的例子

<style>
div {
    margin:10px auto;
    width:300px;
    float:left;
}

.child {
    margin:10px;
    width:100px;
    height:100px;
    float:left;
}
</style>

<div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
</div>
  • 不管是父或子元素,只要是有指定 float 屬性的話,父子元素不會發生相沖現象。
  • 指定了 float 屬性以後,margin: auto; 的值必定歸 0。
  • 即使鄰近的元素也指定了 float,也不會構成相沖。

當使用 float 時,該元素的 margin 效果就會變得像 padding 一樣。

float 鄰接指定了 margin 的元素的情況下

在父子元素指定 float 不會導致相沖。
不過當 float 是鄰接著它們的話,margin 和 float 就會發生相沖。
以下是相沖的基本條件。

  • float 鄰接著別的元素
  • 鄰接著的元素被指定了 margin
  • 鄰接著的元素沒被指定 float

會觸發的條件不限於以上所述的例子。
基於不同情況下會引起相沖或不相沖,在這兒就先捨棄其中一部份的說明。

以下是 margin 和 float 相沖的例子。

<style>
img {
    float:left;
    margin:0 10px;
}
.test {
    margin-top:96px;
}
</style>

<img src="dummy.jpg" alt="" width="100" height="100" />
<img src="dummy.jpg" alt="" width="100" height="100" />
<img src="dummy.jpg" alt="" width="100" height="100" />
<div class="test">float 和 margin 的相沖</div>

只有一個元素被指定 margin 和 float 的話是不會引起 margin 的相沖。

可是,在上面的例子中可以看見,margin 和 float 滿足了相沖所需的條件,結果就會像圖中所示的動作一樣。
以及這樣的相沖,跟解除 float 的 clear 屬性也有著關係。

clear 不是用來解除 float 屬性的

經常有人說 clear 屬性是用來「解除 float」的,它其實是指示 float 要不要鄰接其他元素的一個屬性來的。
當中的動作跟剛才的例子非常相似。

clear 屬性的規格

Values other than ‘none’ potentially introduce clearance. Clearance inhibits margin collapsing and acts as spacing above the margin-top of an element. It is used to push the element vertically past the float.

Computing the clearance of an element on which ‘clear’ is set is done by first determining the hypothetical position of the element’s top border edge. This position is where the actual top border edge would have been if the element’s ‘clear’ property had been ‘none’.

Source: 9.5.2 Controlling flow next to floats: the ‘clear’ property - W3C Visual formatting model

clear 會抑制 margin 的相沖,使得元素像接近 float 的底部般,margin-top 的值會採取自動調整般的舉動。
在 clear: none; 的情況下,會作出正常舉動。

以下是 margin, float, clear 的例子。

<style>
img {
    float:left;
}
.right {
    float:right;
    width:80px;
    height:240px;
    margin-bottom:10px;
}
.clear {
    margin-top:3000px;
    clear:left;
}
.clear-right {
    margin-top:-1000px;
    clear:right;
}
</style>

<img src="dummy.jpg" alt="" width="80" height="80" />
<img src="dummy.jpg" alt="" width="80" height="80" />
<img src="dummy.jpg" alt="" width="80" height="80" />

<div class="right"></div>

<div class="clear">clear:left;</div>
<div class="clear-right">clear:right;</div>

.clear 已被指定成 margin-top: 3000px。理應中間會有 3000px 的間隔,但是它緊接著指定了 float: left 的 img 的底部。
這就是 clear 有的規格。
因為指定了 clear: left;,margin-top 會自動調整,含有 float: left; 的元素便會緊接著前面的。

同時,指定了 float: right; 的 .right 的底部(含 margin),跟 .clear-right 重疊起來了。
這個情況並不是 margin-top 在調整 .right 的頂部至底部。
其實它在調整從 .clear 至 .right 底部的距離。

要說為什麼,雖然那些指定了 float 的隣接元素和 margin 會變成相沖關係,但是像 .clear 般的隣接元素不會跟 margin 發生相沖關係的情況下,那兒才是出發點。

如果要同時使用 clear 和 margin-top 的話,要注意 clear 屬性是會優先處理的。

相沖的優點

雖然是麻煩又複雜的 margin,但當要給予適當間隔的時候……
利用相沖等等技巧,在很多情況下都能寫出整潔的代碼。
來把一個結構以寫成 margin 和 padding 的方式比較一下。

已完成的結構

margin
<style type="text/css">
dl {
    margin: 3em 0;
}
dt {
    display: inline;
    float: left;
}
dd {
    margin: 1em 0 3em 120px;
}
p {
    margin: 1em 0;
}
</style>

<dl>
    <dt>margin Demo 1</dt>
    <dd>從 dd 元素中直接輸入文字</dd>

    <dt>margin Demo 2</dt>
    <dd>
        <p>把 p 元素放進 dd 元素裡。</p>
        <p>dd 和 p 的 margin 重疊,產生相沖。</p>
    </dd>

    <dt>margin Demo 3</dt>
    <dd>
        <img src="dummy.jpg" alt="" width="480" height="32">
        <p>即使插入圖像也會空出間隔來。</p>
        <p>再往下插入也沒有問題。</p>
        <img src="dummy.jpg" alt="" width="480" height="32">
        <p>繼續往下插入也沒有問題。</p>
    </dd>
</dl>
padding
<style type="text/css">
 /* CSS Reset */
dl, dd, p {
    margin: 0;
}

dl {
    padding: 3em 0;
}

dt {
    display: inline;
    float: left;
}

dd {
    padding: 0 0 3em 120px;
}

.pt {
    padding-top: 1em;
}

.pb {
    padding-bottom: 1em;
}

.last-child {
    padding-bottom: 0;
}
</style>

<dl>
    <dt>margin Demo 1</dt>
    <dd>從 dd 元素中直接輸入文字</dd>

    <dt>margin デモ2</dt>
    <dd>
        <p class="pb">把 p 元素放進 dd 元素裡。</p>
        <p>因為要給予 p 元素間隔,不得不加 class 進去。</p>
    </dd>

    <dt>margin Demo 3</dt>
    <dd class="last-child">
        <img src="dummy.jpg" alt="" width="480" height="32">
        <p class="pt pb">插入圖像的話會變成 class 祭典。</p>
        <p class="pb">打算想加入一個新的 p 元素,不得不加 class 進去。</p>
        <img src="dummy.jpg" alt="" width="480" height="232">
        <p class="pt">過份增加 class 了。</p>
    </dd>
</dl>

這是利用了 margin 的相沖和 padding 來建立結構的比較圖。
使用 padding 的話,於最後的元素要指定 padding-bottom: 0;,把 class 分得更細了。
像是用 .mt10, .mt20等等的人,多數都是利用 padding 來指定。

相對來說,利用 margin 的相沖技巧,HTML 和 CSS 雙方都能縮短代碼量。
也能保持適當的間隔,特別是對於以常規動作插入但沒指定 CSS 的 img 來說,某程度還更好地進行維護。

上面就是恰當地使用相沖的例子。
於設計上來說,父元素若加入了 border, padding 等等屬性,有機會不能使用相沖。
可是,能理解相沖的話,書寫 HTML 或 CSS 的效率將會有所改變。

瀏覽器的預設 CSS

於瀏覽器預設的 CSS,跟 margin 是有關連的。
像是 h1 或 p 等等元素,在瀏覽器早已有 CSS 加載。

h1 {
    margin:0.67em 0;
    font-size:2em
}

p {
    margin:1em 0;
}

這是會預算到有相沖為前提,所以才會在上下指定 margin。
根據這份 CSS,於「文章」恰當加入 markup 的話,便能保持適當的間隔。

當要用預設 CSS 發揮其作用去構築結構時,相沖這方面的考慮將會變得更重要。

經常都會被 margin 的規格和 bug 給難到。
折騰 margin 必須要有一定經驗和深入理解的程度才會成功。
解決 margin 的 bug 的方法也有很多,用作 CSS 的主要構築之上應該會成為一個很有用的屬性。

分享到:
评论

相关推荐

    css中margin的缩写

    我们按照顺时针的方向顺序把margin缩写,顺序和方向必须是上右下左

    CSS的margin和padding

    你真的了解margin吗?...写css,你少不了与margin打交道,而对于这个平时我们最常用的css属性我们并非十分了解。介于此我打算写下这篇文章,一来是自己工作中的总结,也是对自己知识的一次梳理。 Margin是什么

    Css padding和margin区别

    这个一个CSS padding和margin的例子,对初学者很有帮助的哦~ .divcss3{border:1px solid #F00;width:400px;margin-left:15px; padding-left:35px;} .box2 { margin-left:10px; padding-left:15px; width:300px...

    浅谈css margin重叠

    父子元素margin重叠 ...以上这篇浅谈css margin重叠就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持软件开发网。 原文地址:http://www.cnblogs.com/lj1028/p/5683253.html

    css中子元素设置margin-top为什么影响了父元素

    本文介绍了css中子元素设置margin-top为什么影响了父元素,分享给大家,具体如下: &lt;style type="text/css"&gt; *{ margin: 0px; padding: 0px; } .show{ margin: 0px auto; width: 200px; height: ...

    一个关于css中margin-right没有效果的问题

    今天在群里面,有人抛出了一个关于css中margin-right没有效果的问题。CSS代码和HTML代码如下: 复制代码代码如下: .style1{ width:400px; height:440px; background-color:red; border:5px solid silver; margin-...

    CSS margin(外边距)

    CSS margin(外边距) CSS margin(外边距)属性定义元素周围的空间。 margin margin 清除周围的(外边框)元素区域。margin 没有背景颜色,是完全透明的。 margin 可以单独改变元素的上,下,左,右边距,也可以一次...

    css中padding、margin两个重要属性的详细介绍及举例说明

    css中padding、margin两个重要属性的详细介绍及举例说明

    css margin-left在IE6下的问题的解决方法

    比如原来是margin-left:20px,经过ie6的解释会变成40px 解决办法是在原来的margin-left后再加上一个_margin-left:10px,变成margin-left:20px;_margin-left:10px 后者的样式将只适用于ie6 问题解决

    css盒子模型 css margin 外边框合并

    刚刚看了css教程觉得很形象就贴出来了。想学习的朋友可以参考下。

    css margin 属性 详细使用说明

    CSS margin 属性 设置外边距的最简单的方法就是使用 margin 属性。 margin 属性接受任何长度单位,可以是像素、英寸、毫米或 em。 margin 可以设置为 auto。更常见的做法是为外边距设置长度值。下面的声明在 h1 元素...

    请不要告诉我你懂css margin

    写css,你少不了与margin打交道,而对于这个平时我们最常用的css属性我们并非十分了解。介于此我打算写下这篇文章,一来是自己工作中的总结,也是对自己知识的一次梳理。 Margin是什么 CSS 边距属性定义元素周围的...

    CSS 之margin知识点(必看)

    下面小编就为大家带来一篇CSS 之margin知识点(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    CSS margin 属性定义边外补白

    边框的外面可以有一层边外补白(margin),边外补白可以把块级元素分开.边外补白定义了围绕某种元素(elements)的空白. 可以查看盒模式,了解边外补白和边内补白. 边外补白分为上边外补白(top),下边外补白(bottom),左边外...

    css margin属性深入解析

    本文将详细介绍css margin属性,需要了解其妙用的朋友可以参考下

    CSS CSS CSS

    CSS CSS 资料套装 CSS CSS 资料套装 CSS CSS 资料套装 CSS CSS 资料套装 CSS CSS 资料套装 CSS CSS 资料套装 CSS CSS 资料套装

    CSS margin全面了解

    下面小编就为大家带来一篇CSS margin全面了解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,祝大家游戏愉快哦

Global site tag (gtag.js) - Google Analytics