1. 程式人生 > >【轉】深入理解margin

【轉】深入理解margin

盒模型 mbed 推理 日誌 onf cap limited textarea 效果

由淺入深漫談margin屬性

技術分享

margin 在中文中我們翻譯成外邊距或者外補白(本文中引用外邊距)。他是元素盒模型(box model)的基礎屬性。

一、margin的基本特性

margin 屬性包括 margin-top, margin-right, margin-bottom, margin-left, margin,可以用來設置 box 的 margin area。屬性 margin 可以用來同時設置 box 的四邊外邊距,而其他的 margin 屬性只能設置其自各的外邊距。

margin 屬性可以應用於幾乎所有的元素,除了表格顯示類型(不包括 table-caption, table and inline-table)的元素,而且垂直外邊距對非置換內聯元素(non-replaced inline element)不起作用。

或許有朋友對非置換元素(non-replaced element)有點疑惑,稍微幫助大家理解一下。非置換元素,W3C 中沒有給出明確的定義,但我們從字面可以理解到,非置換元素對應著置換元素(replaced element),也就是說我們搞懂了置換元素的含義,就懂了非置換元素。置換元素,W3C中給出了定義:

“An element that is outside the scope of the CSS formatter, such as an image, embedded document, or applet”

從定義中我們可以理解到,置換元素(replaced element)主要是指 img, input, textarea, select, object 等這類默認就有 CSS 格式化外表範圍的元素。進而可知,非置換元素(non-replaced element)就是除了 img, input, textarea, select, object 等置換元素以外的元素。

margin 始終是透明的。

二、margin 的基本寫法

外邊距的 margin-width 的值類型有:auto | length | percentage

percentage:百分比是由被應用 box 的containing block(註:一個元素的 containing block 是該元素產生的 box(es)在計算位置和大小時參考的一個矩形)的大小所決定。對於 margin-top 和 margin-bottom 也同樣成立。

margin 的默認值為 0,並且 margin 支持負值。

上面我們曾提到屬性 margin 可以用來同時指定 box 的四邊外邊距。如果屬性 margin 有四個值,那麽值將按照上-右-下-左的順序作用於四邊,即從元素的上邊開始,按照順時針的順序圍繞元素。表達式如下:

margintop right bottom left

四個數值中間以空格分隔。效果等同於:

margin-top:value;
margin-right:value;
margin-bottom:value;
margin-left:value;

並且規範還提供了省略的數值寫法,基本原則如下:

  1. 如果沒有 left 值,則使用 right 代替;
  2. 如果沒有 bottom 值,則使用 top 代替;
  3. 如果沒有 right 值,則使用 top 值代替。

根據這些基本原則,我們可以有三種省略方式,但不管怎樣省略 margin 的數值都會大於等於一個,而 margin 的默認數值是從 top 開始至 left 結束,那麽對於省略的具體情況,我們可以從 left 反推理回去。

1、如果 margin 只有三個值,按照值的順序為 margin:top right bottom; 缺少了 left,根據原則,則 left 的值有 right 來代替。margin:10px 20px 30px; 就等於 margin:10px 20px 30px 20px;

2、如果 margin 只有兩個值,按照值的順序為 margin:top right; 缺少了 bottom 和 left,根據原則 left 的值由 right 來代替,bottm 的值由 top 來代替。margin:10px 20px; 就等於 margin:10px 20px 10px 20px;

3、如果 margin 只有一個值,按照值的順序為 margin:top; 缺少了 bottom、left 和 right,根據原則 left 的值由 right 來代替,bottom 的值由 top 來代替,right 的值右 top 來代替,也就是說 left 的值也由 top 來代替。margin:10px; 就等於 margin:10px 10px 10px 10px;

三、margin的解析邏輯

目前我們已經了解到了 margin 的基本特性和基本寫法,但對元素 margin 的基本解析邏輯還是很模糊,到底 margin 的 top、right、bottom、left 都是以什麽為基準來促使 box model 形成。為了形象,易懂的對 margin 的邏輯進行說明,下面講解的過程中,將引入 W3C 上沒有的參考線的說法。何謂參考線?參考線就是 margin 移動的基準點,此基準點相對於 box 是靜止的。而 margin 的數值,就是 box 相對於參考線的位移量。

在 margin 中 top、right、bottom、left 的參考線並不一致為一類,而是分為了兩類參考線,top 和 left 的參考線屬於一類,right 和bottom 的參考線屬於另一類。那他們到底各以什麽為參考線呢?top 以 containing block 的 content 上邊或者垂直上方相連元素 margin 的下邊為參考線垂直向下位移;left 以 containing block 的 content 左邊或者水平左方相連元素 margin 的右邊為參考線水平向右位移。right 以元素本身的 border 右邊為參考線水平向右位移;bottom 以元素本身的border 下邊為參考線垂直向下位移。從上我們可以看到 top 和 left 都是以外元素為參考,而 right 和 bottom 以本元素為參考。上面的位移方向是指 margin 數值為正值時候的情形,如果是負值則位移方向相反。

技術分享

或許理論聽起來比較枯燥,我們舉例說明一下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<style type="text/css">
div {
width:200px;
height:200px;
background:#ccc;
}
</style>
</head>

<body>
<div>外邊距的margin-width的值類型有:auto | length | percentage</div>
</body>
</html>

如上代碼,很簡單,為了方便我們看到效果,我們給 div 設置了寬度和高度以及背景色。

現在我們給 div 的樣式加上 margin 屬性,比如:

margin:-10px 20px -30px 40px;

這時候 margin 的解析邏輯是怎樣的呢?首先我們要搞清 div 的和周邊元素的關系,div 沒有相連元素,而此時 div 的 containing block 是 body 產生的 block box。則根據上面介紹的參考線原理,div 的左外邊距以 containing block 的 content 左邊為參考線,及此時以 body 的 content 左邊為參考線進行水平向右位移,位移的大小為 40px,同理,上邊距以 body 的 content 上邊為參考線進行垂直向上位移 10px(負值和正值的方向相反),下邊距依照現在 div 的 borer 下邊(此時的 div 已經經過上邊距位移過了)垂直向上位移 30px(此時,margin 不會改變 box 的 border 內的物理大小,但會改變 box 的邏輯大小,即:以此 box 的 margin 的下邊為參考的元素,不是從 box 的物理位置開始的,而是從邏輯位置開始),右邊距依照現在 div 的 borer 右邊(此時的 div 已經經過左邊距位移過了)水平向右位移 20px。或許有朋友問你分析的順序怎麽和 margin 表達式中出現的順序不一樣?如果按照 margin 表達式中出現的順序來分析,結果是一樣的,只是為了更好的方便大家的理解而沒有按照表達式的順序來分析。

技術分享

用 margin 最後的實際顯示大小的到底是怎麽樣呢,或許有朋友也比較疑惑,我暫時用邏輯大小和物理大小來區分(其實上面已用到此概念),到底什麽是邏輯大小,什麽是物理大小呢?!具體可以看圖,物理大小指的是除去 margin,也就是包含 border 以內的 box 大小,而邏輯大小,則是 box 通過 margin 解析規則解析後得到的大小(這或許可以解釋為什麽IE5會錯誤解析盒模型)。在上圖中,box 的實際顯示的寬度等於 box 的邏輯大小,而 box 實際顯示的高度等於 box 的物理大小,這說明 box 實際顯示的大小可能是 box 的邏輯大小,也可能是 box的 物理大小,規則到底是怎樣的——

box 的實際大小 = box 的物理大小 + 正的 margin

這僅對元素本身有效,對於其後面的相關元素,他們則只以 margin 的邏輯大小為準則,進行布局。

有朋友反應,聽得很迷糊,越看越不懂,如果你對具體的理解過程不感興趣的話,那記住下面我總結的結論就可以了,XD

結論:

box 最後的顯示大小等於 box 的 border 及 border 內的大小加上正的 margin 值。而負的 margin 值不會影響 box 的實際大小,如果是負的 top 或 left 值會引起 box 的向上或向左位置移動,如果是 bottom 或 right 只會影響下面 box 的顯示的參考線。

  • CSS Expression 的優化
  • 影響 reflow 的因素及其優化
  • 如何快速定位頁面中復雜 CSS BUG 問題
  • 可以給img元素設置背景圖
  • Google Chrome 瀏覽器支持的 CSS 選擇器
  • position:relative 的使用限制
  • line-height 屬性的繼承問題
  • 如何給 legend 標簽設定寬度
  • 如何跨瀏覽器使用連續字符的換行
  • 兩個不太常用的 CSS Hack

【原文】http://www.planabc.net/2007/03/18/css_attribute_margin/

【轉】深入理解margin