CSS葵花寶典——盒模型

CSS假定每個元素都會生成一個或者多個矩形框,這稱為元素框(規范的將來版本可能允許非矩形框,不過對現在來說,框都是矩形的)。各元素框中心有一個內容區(content area)。這個內容區周圍有可選的內邊框、邊框和外邊框?!禖SS權威指南》

任何一個頁面,都是由一個一個的盒子構成;而每個元素,其實都是一個矩形盒子,也就是所謂的盒模型;所以,寫一個頁面,無非就是把這些盒子按照一定方式進行排列,是不很簡單——凡是都是盒子

以Google的開發者網站來展示:

先拆分成兩個大盒子(紅色虛線標準),然后在每個大盒子中又包括很多小盒子(你看,文字也是由矩形框包圍起來的),把這些盒子進行布局排版,再加上視覺效果,這個頁面就可以寫出來了。

盒模型基本結構

扯了這么多,具體看看一個盒子是怎么樣的:

一個盒子,從內到外,分別是content(內容區域)、padding內邊距、border(邊框)、margin(外邊距);

padding , border , margin 都可以對 top, right,bottom,left4個方向單獨進行設置。

.box{
  height: 300px; /* content 高度 */
  width: 300px;  /* content 寬度 */
  border: 1px solid #333;  /* 上下左右都是1px的邊框,顏色為#333的實線 */
  margin-top: 80px; /* 僅設置 margin top */
  padding: 40px; /* 上下左右都是 40px padding */
}

具體說下padding,margin四個方向的設置:

.box{
  margin-top: 25px;
  margin-bottom: 25px;
  margin-left: 40px;
  margin-right: 40px;
}

等同于

.box{
  margin: 25px 40px;
}

等同于

.box{
  margin: 25px 40px 25px 40px;
}

看明白了唄,設置padding或者margin的上下左右四個值,你可以單獨用

padding/margin-top,padding/margin-bottom,padding/margin-left,padding/margin-right

有時候也可以直接為padding/margin設置4個值(順序固定),從top順時針繞一圈:

padding/margin: top right bottom left

還可以為padding, margin指定少于4個值,規則如下

如果缺少左外邊距,則使用右外邊距
如果缺少下外邊距,則使用上外邊距
如果缺少右外邊距,則使用上外邊距

padding和margin的區別

為了便于理解,你可以認為,margin是不屬于這個盒子的,僅僅是為了占據空間;而padding是作為盒子的一部分。

從視覺上來講

padding的顏色是跟背景色一樣的,所以你給元素設置了背景色,padding也會受影響;而margin永遠都透明的。

從實踐來看

  • marginpadding都可以用來把盒子和盒子分開

    但是padding還可以把內容和border分開

  • margin存在Margin Collapse的特點,padding不會存在

    Margin Collapse`深入的內容,參看透析Margin Collapsing

建議:實際開發看著辦就好,只要保持用margin和padding使用習慣上的統一就OK

更多關于marginpadding的討論,參見 When to use margin vs padding in CSS

Box Sizing

寫 CSS 的時候,在 margin、padding、border存在的情況下,盒子實際占據的空間可能和預期不同,我們需要確定在 CSS 中 width,height 到底是包含哪些部分(content, padding, margin, border),具體的計算規則由 box-sizing 指定。

已知一個盒子的規則如下:

.box{
  width: 300px;
  height: 200px;
  padding: 5px;
  border: 2px solid;
}

問:這個盒子實際占據空間多大?

正確的計算如下:
實際占據空間寬度 =

width(300) + padding-left(5) + padding-right(5) + border-left(2) + border-right(2)

= 314px

content-box

我們的盒子的box-sizing默認值是content-boxheightwidth僅僅是content的高度和寬度,并不包括paddingborder。所以你在考慮這個盒子占用的空間時,需要手動算上paddingborder

有時候莫名其妙水平方向有了滾動條、或則父元素寬度不夠,都是因為忽略了paddingborder的寬度。

下邊的這個列子會因為border的存在而出現滾動條:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
  <title>測試</title>
  <style type="text/css">
    html, body{
      width: 100%;
      height: 100%;
    }
    .box{
      border-left: 2px;
      width: 100%;
    }
  </style>
</head>
<body>
  <div class="box">Content Box</div>
</body>
</html>

border-box

如果將box-sizing設置為border-box,高度和寬度就會包含paddingborder,這樣才符合我們的習慣。

修改上面的例子,避免出現滾動條,設置成border-box就好了:

.box{
  box-sizing: border-box; 
}

box-sizing 實戰應用

為了避免不必要的麻煩,建議將所有元素都設置成border-box,推薦寫法:

html {
  box-sizing: border-box;
}
*, *:before, *:after{
  box-sizing: inherit;
}

注意,是通過為根元素html設置border-box,其他元素繼承實現的,而不是像這樣:

* {
  box-sizing: border-box;
}

想想區別在哪,有啥好處

解釋在這:box-sizing best practices

display

不管是 div 也好, a 標簽也好,在頁面中都是一個盒模型的實例,但每個盒子因為 display屬性不同,又可以分為不同的類別(inline, block, inline-block, table 等),在排版上有各自的特點。

The display CSS property specifies the type of rendering box used for an element. In HTML, default display property values are taken from behaviors described in the HTML specifications or from the browser/user default stylesheet. The default value in XML is inline.——MDN/CSS/display

我們說過,頁面中的每個元素都是一個盒子,blockinline 是大多數元素的默認類型。元素以什么樣的方式展現出來,不是根據它是什么元素,而是由display屬性決定。

舉例說明——塊級元素、行內元素

常說的塊級元素行內元素實際包含兩個方面:

  1. HTML的嵌套規則

    一般塊級元素可以包含行內元素和其他塊級元素,而行內元素內不可嵌套塊級元素

  2. 用戶代理默認display屬性值

    W3C為元素指定了默認的display值,用戶代理(瀏覽器)根據W3C的標準,實現默認的樣式規則。

    W3C標準:

    瀏覽器默認樣式

    注: HTML5中已經沒有行內元素和塊級元素的概念,詳細參見Content categories,塊級元素大致相當于HTML5中的Flow Elements,行內元素相當于Phrasing Elements

display 總結

  • 元素以什么樣的盒子渲染,是通過display屬性控制,而非標簽類型
  • 瀏覽器默認樣式為每個元素設置了display默認值
  • display默認值是inline(比如,某些瀏覽器不認識HTML5中的標簽,這些元素的display屬性值就很悲劇都成inline了)
  • 通過display僅僅是改變元素的顯示方式,并未改變標簽類型

display還有很多屬性值,感興趣的參看MDN display章節

block, inline, inline-block 區別

display 明白后,再看下 block, inline, inline-block 各自特點。

我們為 p 標簽設置不同的 display 屬性:

HTML

<body>
    <div>
      block, inline, inline-block舉例:接下來是一個p標簽:<p>display: block</p>,這是p標簽之后的內容。
    </div>
    <div>
      block, inline, inline-block舉例:接下來是一個p標簽,display設置為inline:<p class="inline">display: inline;</p>,這是p標簽之后的內容。
    </div>
    <div>
      block, inline, inline-block舉例:接下來是一個p標簽,display設置為inline-block:<p class="inline-block">display: inline-block</p>,這是p標簽之后的內容。
    </div>

</body>

CSS

div{
  margin-bottom: 3em;
  border: 1px dotted #77C2D4;
}

p{
  height: 2em;
  width: 50%;
  margin-top: 1em;
  padding: 0 1em;
  border: 1px dotted #F9454E;
}
.inline{
  display: inline;
}
.inline-block{
  display: inline-block;
}

效果圖

第一個p標簽,默認是block。height,width,margin-top,padding-left均有效,單獨占一行,注意它的margin-left/right和width的關系!

第二個p標簽,dislplay: inlineheight,width,margin-top都無效了

第三個p標簽,display: inline-block。一切正常,而且不換行

block, inline, inline-block 總結

block

  • (默認)寬度:等于父元素content的寬度
  • (默認)高度:由子元素高度確定
  • width、height 可設置
  • 單獨占一行

inline

  • 設置widthheight無效
  • marginpadding 垂直方向上設置無效
  • 只要寬度足夠,從左往右(對于從左往右閱讀的語言)挨個排列

inline-block

inline-block繼承了inlineblock的特點,W3chools的總結簡直完美:

An inline-block element is placed as an inline element (on the same line as adjacent content), but it behaves as a block element.

  • 可設置widthheight
  • marginpadding垂直方向上有效
  • 不換行

The Display Declaration這篇文章有更多的display屬性的演示和說明

挑戰一下

搞懂 displayblock, inline, inline-block 后,很多頁面你都可以完成了。實現Google開發者網站我們的截圖部分:

建議你拿我們最開始舉例的Google開發者網站練手,要求如下:

  • 不允許用浮動
  • 你要解決 inline-block 可能出現的空白問題
CSS 盒模型 任務

我這不直接貼代碼了,如果實現有問題或者需要參考的,直接聯系我就好了

原文地址:CSS葵花寶典——盒模型-4光年

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

推薦閱讀更多精彩內容