从CSS盒子模型说起

前言

总括: 对于盒子模型,BFC,IFC和外边距合并等概念和问题的总结

为学之道,莫先于穷理;穷理之要,必先于读书。

正文

​ CSS盒子模型是CSS基础中的基础,个人之前对于这块的理解有偏差💔,由于涉及知识点比较多所以写一篇总结备忘。
之前打算的是两周一次更新博文的,但是时间用在了刷题上,做了很多leetcode上算法数据结构的题记录在github,但其实也有在更新啦~只不过是对之前的一些博文进行纠正:)😄

​ 最近秋招在即,压力倍增,前几天把博客导入页的在读大三本科生改为了在读大四本科生,不禁心生感慨,时光荏苒。转眼间我的这个小窝竟然已经快一年了。当初建立这个站点也是想找个说话的地方,有的人可能就是不喜欢说,只喜欢写(比如我),然而自从实习后确实提不起精神来写了,一是没精力,二是对于遇到的一些坑不想单独写一篇博客记录。这里还是想保持一份纯净,就是以总结和理解难点为主调 其它的一般会托管在github库里记录一下。闲话不多说,说说今天的主角🤦‍♀️

​ CSS盒子模型想来都不陌生,但还是想先介绍一下,以保证文章的完整性。😳

盒子模型

​ CSS盒子模型:

盒子模型
盒子模型

在一个文档中,每一个元素都被抽象成一个盒子,每一个盒子又包括四部分(从内到外):内容(content),内填充(padding),边框(border),外边距(margin)。见上图,这是从二维的角度分析,来张三维立体图:😜

网上找的图片

此图很形象的解释了CSS盒子的构成:

  1. content box:立体盒子的核心
  2. padding box:内边距区域padding area 延伸到包围padding的边框。如果内容区域content area设置了背景、颜色或者图片,这些样式将会延伸到padding上(当然我们可以通过background-clip设置作用区域)
  3. border box:由border和4条border edge组成。若border宽度设置为0,则border edge与padding edage重叠;
  4. margin box:由margin和4条margin edge组成。若margin宽度设置为0,则margin edge与border edage重叠。

😨看起来很复杂的样子...

拿PS图层的概念更好理解这块,最上面的就是content box往下一次是padding box,border box,margin box。

那么盒子模型一般分为两种:

IE盒子模型

所谓IE盒子模型,就是之前IE浏览器实现的一种怪异的盒子模型,怎么怪异呢?当我们这样设置的时候:

div {
    width: 100px;
    height: 100px;
}

理论上我们想要设置的就是content box的宽高嘛,但是IE在解析的时候会按照这个规则解析:

width = content-width + padding-width + border-width
height = content-height + padding-height + border-height

这就导致了这种尴尬的境地:下面无内容的话直接戳这里😓

<script async src="https://jsfiddle.net/Damonare/f7vh400t/embed/html,css,result//"></script>

标准盒子模型

标准就比较符合常人的思维了,设置的width,height就是content的width和height

规则就是:

width = content-width

height = content-height

实例如下:无内容戳这😓

<script async src="https://jsfiddle.net/Damonare/a6oogyyz/embed/html,css,result/"></script>

可能秉着宽大为怀的准则,CSS3加了个box-sizing属性,变相承认了这两种盒子都对(好吧,可能一个人有一个人的看法吧),不过box-sizing默认属性就是content-box,即标准盒子模式,IE盒子模型呢,是属性border-box。刚刚查MDN发现还有一个属性padding-box(width=content-width+padding-width),不过并没有浏览器实现它(真可怜),并无卵用🤣

行内元素的思考

刚刚说的是以块级元素为例说的,那么行内元素呢?好吧,其实你知道,行内盒是没法设置width和height的,那么之前我就有了这样的思维定势:行内盒没有padding,margin,然后发现,哦!行内盒是有padding-left,padding-right,margin-left,margin-right的!WOC!,然后又发现,行内盒是实际上身怀八甲...😷

以下无内容戳这里

<script async src="https://jsfiddle.net/Damonare/826gyrrh/embed/html,css,result/"></script>

行内盒子的高由font-size决定的;
行内盒子的宽等于其子行级盒子的外宽度(margin+border+padding+content width)之和。

是有padding-top和padding-bottom,margin-left,margin-bottom的但并不占据空间…这就符合盒子模型了嘛,既都是盒子,自然应该是一样的。行内盒的margin-top, margin-bottom不占空间,由此联想到了另一个问题——😑

外边距合并

所谓外边距合并呢,就是margin合并嘛,看下MDN的定义:

块的顶部外边距和底部外边距有时被组合(折叠)为单个外边距,其大小是组合到其中的最大外边距,这种行为称为外边距合并

😱注意只是上下,没有说左右。而且是针对块级元素说的。

外边距合并有这几种情况:

相邻兄弟元素

//HTML
<div class="up">我在上面</div>
<div class="down">我在下面</div>
//CSS
.up {
  width: 100px;
  height: 100px;
  border: 1px solid blue;
  margin: 100px;
}
.down {
  width: 100px;
  height: 100px;
  border: 1px solid red;
  margin: 100px;
}

我们感性上觉得上下两个元素应该是相差200px距离,然而并不是。

父子元素

如果块级父元素中,不存在上边框、上内补、inline content、清除浮动这四条属性(对于上边框和上内补,也可以说,当上边距及上内补宽度为0时),那么这个块级元素和其第一个子元素的上边距就可以说”挨到了一起“。此时这个块级父元素和其第一个子元素就会发生 上外边距合并 现象,换句话说,此时这个父元素对外展现出来的外边距将直接变成这个父元素和其第一个子元素的margin-top的较大者。😊

//HTML
<div class="parent">
  <div class="child">我是儿子</div>
</div>
//CSS
.parent {
  width: 100px;
  height: 200px;
  background: red;
  margin-left: 100px;
}
.child {
  width: 50px;
  height: 50px;
  margin-top: 100px;
  border: 1px solid blue;
}

上面代码感性上可能会觉得,父元素没有上边距,然而并不是。

MDN给了三种情况,但第三种空块元素,我觉得可以包含在这两种之内,就没举🌰

那么这种外边距合并的情况咋解决呢?看下一个概念...

BFC

😯定义:

一个块格式化上下文(block formatting context) 是Web页面的可视化CSS渲染的一部分。它是块盒子的布局发生,浮动互相交互的区域。

那么触发BFC的情况有哪些呢?

看MDN:

😱一个块格式化上下文由以下之一创建:

  • 根元素或其它包含它的元素
  • 浮动 (元素的float 不是 none)
  • 绝对定位的元素 (元素具有 positionabsolutefixed)
  • 内联块 inline-blocks (元素具有 display: inline-block)
  • 表格单元格 (元素具有 display: table-cell,HTML表格单元格默认属性)
  • 表格标题 (元素具有 display: table-caption, HTML表格标题默认属性)
  • 块元素具有overflow ,且值不是 visible
  • display: flow-root

注意,根元素就创建了一个BFC

那么BFC又有一下特性:

  1. 内部块级盒子垂直方向排列
  2. 盒子垂直距离由margin决定,同一个BFC的盒子外边距会合并
  3. BFC就是一个隔离的容器,内部子元素不会影响到外部元素
  4. 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  5. BFC的区域不会与float box叠加。

好,上面外边距合并的两种情况,利用BFC如何解决呢?下面没内容的话请戳这里😓

<script async src="https://jsfiddle.net/Damonare/ejntapom/embed/html,css,result/"></script>

关于第四五条特性,请看上面的示例。

BFC用途:

  1. 清除浮动;
  2. 解决外边距合并;
  3. 布局;

块级盒子的概念

关于这块有好多个概念...首先是块级元素和块级盒子:每个块级元素至少生成一个块级盒,称为主要块级盒。一些元素,比如li,生成额外的盒来放置项目符号,不过多数元素只生成一个主要块级盒。

主要块级盒将包含后代元素生成的盒以及生成的内容。它也是可以使用(定位方案 positioning scheme)的盒。

块容器盒(block container box) 只包含其它块级盒,或生成一个行内格式化上下文(inline formatting context)

注意块级盒与块容器盒概念不同。 前者描述元素跟它的父元素与兄弟元素之间的表现,后者描述元素跟它的后代之间的影响。

同时是块容器盒的块级盒称为块盒(block boxes)。(注意块盒和块级盒并不是全等)

还有一个特殊的块盒——匿名块盒

<div>Some inline text <p>followed by a paragraph</p> followed by more inline text.</div>
//将创建两个匿名块盒,一个包含 <p> 前面的文本 (Some inline text), 一个包含 <p> 后面的文本(followed by more inline text), 

块级元素触发BFC,行内元素会触发啥么❓

IFC

IFC 只有在一个块级元素中仅包含内联级别元素时才会生成。

行内盒子的概念

当元素的 CSS 属性 display的计算值为 inline, inline-blockinline-table时,称它为行内级元素。视觉上它将内容与其它行内级元素排列为多行。典型的如段落内容,有文本(可以有多种格式譬如着重),或图片,都是行内级元素。

行内级元素生成行内级盒(inline-level boxes),参与行内格式化上下文(inline formatting context)。同时参与生成行内格式化上下文的行内级盒称为行内盒(Inline boxes)。所有display:inline 的非替换元素生成的盒是行内盒。而不参与生成行内格式化上下文的行内级盒称为原子行内级盒(*atomic inline-level boxes)。这些盒由可替换行内元素,或 display 值为 inline-blockinline-table的元素生成,不能拆分成多个盒。

另外CSS3还新增了两种格式上下文:GFC(Grid Formatting Contexts)栅格格式化上下文和FFC(Flex Formatting Contexts)Flex格式化上下文,即分别在元素display为grid和flex、 inline-flex 时触发

定位

常规流

分清了这些盒子的概念,具体怎么排列呢?以下来自MDN:

在常规流中,盒一个接着一个排列。在块级格式化上下文里面, 它们竖着排列;在行内格式化上下文里面, 它们横着排列。 当 position为 staticrelative,并且 float 为 none 时会触发常规流。

浮动(Floats)

对于浮动定位方案(float positioning scheme), 盒称为浮动盒(floating boxes)。它位于当前行的开头或末尾。这导致常规流环绕在它的周边,除非设置 clear 属性。

要使用浮动定位方案,元素 CSS 属性position 为 staticrelative,然后float不为none 。如果 float设为 left, 浮动由行盒的开头开始定位。如果设为 right, 浮动定位在行盒的末尾。

绝对定位(Absolute positioning)

对于绝对定位方案, 盒从常规流中被移除,不影响常规流的布局。 它的定位相对于它的包含块,相关CSS属性:top, bottom, left及right 。

如果元素的属性position为 absolutefixed, 它是绝对定位元素。

固定定位元素(fixed positioned element)也是绝对定位元素,它的包含块是视口。当页面滚动时它固定在屏幕上,因为视口没有移动。

以上。

后记

参考文章

外边距塌陷

Box model

Block formatting context

视觉格式化模型

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

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,737评论 1 92
  • 引言 这次给大家带来了CSS-盒子模型部分的笔记,大家一同交流😊 认识盒子模型之前,先来了解一下CSS元素的分类吧...
    zhaolion阅读 4,300评论 9 85
  • •前端面试题汇总 一、HTML和CSS 21 你做的页面在哪些流览器测试过?这些浏览器的内核分别是什么? ...
    Simon_s阅读 2,220评论 0 8
  • CSS假定每个元素都会生成一个或者多个矩形框,这称为元素框(规范的将来版本可能允许非矩形框,不过对现在来说,框都是...
    四光年阅读 821评论 0 10
  • 1.CSS基本概念 1.1 CSS的定义 CSS(Cascading Style Sheets)层叠样式表,主要用...
    寥寥十一阅读 1,825评论 0 6