`

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 的主要構築之上應該會成為一個很有用的屬性。

分享到:
评论

相关推荐

    Dreamweaver CS6 CSS样式汉化文件

    "CS6 CSS样式表的汉化文件.txt"很可能是一个文本文件,其中包含了汉化过程的说明或翻译后的CSS样式表的文本内容。这个文件可能是为了指导用户如何安装汉化包,或者记录了每个CSS属性名称及其对应的中文翻译,以便在...

    css教程css理解

    - **CSS框模型**: 包括边距(margin)、边界(padding)、边框(border)和内容(content)。 - **CSS定位**: 有静态(static)、相对(relative)、绝对(absolute)和固定(fixed)等多种定位方式。 - **CSS高级功能**: 如响应式...

    css_hack csshack技术

    2. **尽量减少使用Hack**:虽然CSS Hack很有用,但过度依赖会导致维护困难。尽可能采用标准CSS来实现兼容性。 3. **测试**:在实际部署前,务必在目标浏览器中进行全面测试,确保所有Hack按预期工作。 #### 六、...

    css优先级总结

    - **外边距**:`margin-top`和`margin-bottom`对行内元素无效,只有`margin-left`和`margin-right`有效。 - **溢出**:行内元素的`overflow`属性无效。 - **垂直对齐**:`vertical-align`属性仅适用于行内元素。 ##...

    压缩JS和CSS工具

    - **缩写属性值**:许多CSS属性值有缩写形式,如`margin: 0 auto;`可以简化为`margin: 0 auto;`。 TBCompressor是一款用于JS和CSS压缩的工具,它可能提供了如下功能: - **批量处理**:一次性处理多个JS或CSS文件...

    css新手帮助提示功能

    "CSS新手帮助提示功能"是为了缓解这种困难而设计的一种辅助工具,它旨在为初学者提供即时的帮助和指导,让他们能够更轻松地理解和应用CSS。下面将详细探讨这一功能及其相关知识点。 首先,我们要理解CSS的基本结构...

    CSS中的边界margin的取值为负值说明

    在CSS(层叠样式表)中,边界margin的取值确实可以是负值,这是一个非常实用且富有创意的特性。负边距可以帮助我们调整元素的位置,实现一些特殊布局或者交互效果,尤其在处理复杂的网页布局时能发挥重要作用。让...

    CSS基础知识-1(1).md

    ### CSS基础知识详解 #### 一、CSS简介 - **1.1 HTML的局限性** HTML是一种用于构建网页内容的标准标记语言。它关注于描述网页的内容及其语义,例如使用`&lt;h1&gt;`标签来定义一级标题,使用`&lt;p&gt;`标签来表示段落等。...

    非常好的CSS帮助文档,让你更好的学习

    1. 盒模型:理解CSS盒模型是布局的关键,包括内容(content)、内边距(padding)、边框(border)和外边距(margin)。 2. 浮动(float):用于创建多列布局,元素会浮动到左侧或右侧,其他元素围绕其排列。 3. 定位(position...

    纯css标题框圆角代码

    传统的做法通常是使用图像来设计,但这种方法存在一些局限性,例如响应式设计困难、加载速度慢等。随着CSS技术的发展,我们可以利用纯CSS来实现各种复杂的效果,包括圆角标题框。本篇文章将深入探讨如何使用CSS创建...

    CSS网站布局实录 (第二版)PDF版

    1.6.5 学习CSS布局比表格困难吗 1.6.6 CSS布局是否意味着必须手写代码 1.6.7 什么叫网站重构 1.6.8 使用Web标准之后就不再存在兼容性问题了吗 1.6.9 有没有Web标准方面的优秀图书或网站 1.6.10 使用CSS设计只能做出...

    淘宝网页简单的仿写,html+css

    5. 轮播图插件:如果对原生CSS实现轮播图有困难,可以引入现成的JavaScript轮播图库,如Slick或Swiper。 总之,通过学习和实践这个HTML+CSS的淘宝网页仿写项目,你可以深入了解网页的结构和样式设计,并掌握一系列...

    分享20条编写 CSS 代码的建议

    important可以覆盖其他CSS规则,但会使CSS的维护变得更加困难。只有在别无选择的情况下,才使用它。 15. 使用媒体查询创建响应式设计 媒体查询允许基于不同的屏幕尺寸和设备特性应用不同的CSS样式,这对于制作适应...

    CSS的常用技巧放送

    important`,因为它破坏了CSS的正常继承和层叠规则,使得调试变得困难。 以上这些技巧可以帮助你写出更高效、更易于维护的CSS代码,提升网页设计和开发的质量。熟练掌握这些技巧,将使你的CSS工作更加得心应手。

    CSS彻底底研究

    1. 内容(Content)、内边距(Padding)、边框(Border)和外边距(Margin)构成了CSS盒模型,理解它们有助于控制元素的尺寸和空间布局。 2. IE盒模型与W3C盒模型的区别:在不同浏览器中,盒模型处理方式可能不同,...

    DIV+CSS布局基础

    2. **改版困难**:当需要修改页面布局时,由于内容和样式混合在表格中,改版的工作量非常大。 3. **可读性差**:Table布局将表现和内容混杂在一起,降低了代码的可读性和可维护性。 4. **性能问题**:由于表格元素...

    XHTML CSS基础知识

    如果你对此还不熟悉,建议先进行基础知识的学习,否则直接进入XHTML CSS可能会感到困难。 **1. 文档类型(Document Type)** XHTML文档通常以DOCTYPE声明开始,用于告诉浏览器文档遵循的规范。在例子中提到的`&lt;!...

    DIV+CSS布局实例

    3. **可维护性**:`Table`布局中样式和结构混合,修改困难。`DIV+CSS`将样式定义在外部CSS文件,改动一处,全局生效,降低了维护成本。 4. **SEO优化**:搜索引擎更喜欢结构清晰、代码简洁的`DIV+CSS`布局,有助于...

    CSS+DIV视频教程

    2. **盒模型**:理解CSS盒模型,包括内容(content)、内边距(padding)、边框(border)和外边距(margin),并掌握如何调整元素的尺寸和间距。 3. **定位与布局**:学习相对定位(relative)、绝对定位(absolute)和固定...

    div&css手册来了

    【描述】:“div&css中文手册来了,草蛋不让下在啊,112123424234234”这句描述似乎暗示了用户在寻找关于div和CSS的中文资源时遇到了困难,可能是由于某些下载限制。 【标签】:“div&css”标签明确了这个话题主要...

Global site tag (gtag.js) - Google Analytics