CSS葵花宝典——盒模型

CSS假定每个元素都会生成一个或者多个矩形框,这称为元素框(规范的将来版本可能允许非矩形框,不过对现在来说,框都是矩形的)。各元素框中心有一个内容区(content area)。这个内容区周围有可选的内边框、边框和外边框。——《CSS权威指南》

任何一个页面,都是由一个一个的盒子构成;而每个元素,其实都是一个矩形盒子,也就是所谓的盒模型;所以,写一个页面,无非就是把这些盒子按照一定方式进行排列,是不很简单——凡是都是盒子

以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标签,默认是blockheightwidthmargin-toppadding-left均有效,单独占一行,注意它的margin-left/right和width的关系!

第二个p标签,dislplay: inlineheightwidthmargin-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光年

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容