总括: 对于盒子模型,BFC,IFC和外边距合并等概念和问题的总结css
原文地址:从CSS盒子模型提及html
知乎专栏:前端进击者前端
博主博客地址:Damonare的我的博客git
为学之道,莫先于穷理;穷理之要,必先于读书。github
CSS盒子模型是CSS基础中的基础,我的以前对于这块的理解有误差💔,因为涉及知识点比较多因此写一篇总结备忘。
以前打算的是两周一次更新博文的,可是时间用在了刷题上,作了不少leetcode上算法数据结构的题记录在github,但其实也有在更新啦~只不过是对以前的一些博文进行纠正:)😄算法
最近秋招在即,压力倍增,前几天把博客导入页的在读大三本科生
改成了在读大四本科生
,不由心生感慨,时光荏苒。转眼间个人这个小窝居然已经快一年了。当初创建这个站点也是想找个说话的地方,有的人可能就是不喜欢说,只喜欢写(好比我),然而自从实习后确实提不起精神来写了,一是没精力,二是对于遇到的一些坑不想单独写一篇博客记录。这里仍是想保持一份纯净,就是以总结和理解难点为主调 其它的通常会托管在github库里记录一下。闲话很少说,说说今天的主角🤦♀️浏览器
CSS盒子模型想来都不陌生,但仍是想先介绍一下,以保证文章的完整性。😳数据结构
CSS盒子模型:ide
在一个文档中,每个元素都被抽象成一个盒子,每个盒子又包括四部分(从内到外):内容(content),内填充(padding),边框(border),外边距(margin)。见上图,这是从二维的角度分析,来张三维立体图:😜布局
此图很形象的解释了CSS盒子的构成:
😨看起来很复杂的样子...
拿PS图层的概念更好理解这块,最上面的就是content box往下一次是padding box,border box,margin box。
那么盒子模型通常分为两种:
所谓IE盒子模型,就是以前IE浏览器实现的一种怪异的盒子模型,怎么怪异呢?当咱们这样设置的时候:
div {
width: 100px;
height: 100px;
}复制代码
理论上咱们想要设置的就是content box的宽高嘛,可是IE在解析的时候会按照这个规则解析:
width = content-width + padding-width + border-width
height = content-height + padding-height + border-height
这就致使了这种尴尬的境地:下面无内容的话直接戳这里😓
标准就比较符合常人的思惟了,设置的width,height就是content的width和height
规则就是:
width = content-width
height = content-height
实例以下:无内容戳这😓
可能秉着宽大为怀的准则,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!,而后又发现,行内盒是实际上身怀八甲...😷
行内盒子的高由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给了三种状况,但第三种空块元素,我以为能够包含在这两种以内,就没举🌰
那么这种外边距合并的状况咋解决呢?看下一个概念...
😯定义:
一个块格式化上下文(block formatting context) 是Web页面的可视化CSS渲染的一部分。它是块盒子的布局发生,浮动互相交互的区域。
那么触发BFC的状况有哪些呢?
看MDN:
😱一个块格式化上下文由如下之一建立:
`[
float](https://developer.mozilla.org/zh-CN/docs/Web/CSS/float) 不是
none`)position
为 absolute
或 fixed
)display
: inline-block
)display
: table-cell,HTML表格单元格默认属性
)display
: table-caption
, HTML表格标题默认属性)overflow
,且值不是 visible
display
: flow-root
注意,根元素就建立了一个BFC
那么BFC又有一下特性:
好,上面外边距合并的两种状况,利用BFC如何解决呢?下面没内容的话请戳这里😓
关于第四五条特性,请看上面的示例。
BFC用途:
关于这块有好多个概念...首先是块级元素和块级盒子:每一个块级元素至少生成一个块级盒,称为主要块级盒。一些元素,好比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 只有在一个块级元素中仅包含内联级别元素时才会生成。
当元素的 CSS 属性 display的计算值为 inline
, inline-block
或 inline-table
时,称它为行内级元素。视觉上它将内容与其它行内级元素排列为多行。典型的如段落内容,有文本(能够有多种格式譬如着重),或图片,都是行内级元素。
行内级元素生成行内级盒(inline-level boxes),参与行内格式化上下文(inline formatting context)。同时参与生成行内格式化上下文的行内级盒称为行内盒(Inline boxes)。全部display:inline 的非替换元素生成的盒是行内盒。而不参与生成行内格式化上下文的行内级盒称为原子行内级盒(*atomic inline-level boxes)。这些盒由可替换行内元素,或 display 值为 inline-block
或 inline-table
的元素生成,不能拆分红多个盒。
另外CSS3还新增了两种格式上下文:GFC(Grid Formatting Contexts)栅格格式化上下文和FFC(Flex Formatting Contexts)Flex格式化上下文,即分别在元素display为grid和flex、 inline-flex 时触发
分清了这些盒子的概念,具体怎么排列呢?如下来自MDN:
在常规流中,盒一个接着一个排列。在块级格式化上下文里面, 它们竖着排列;在行内格式化上下文里面, 它们横着排列。 当 position为 static
或 relative
,而且 float 为 none
时会触发常规流。
对于浮动定位方案(float positioning scheme), 盒称为浮动盒(floating boxes)。它位于当前行的开头或末尾。这致使常规流环绕在它的周边,除非设置 clear 属性。
要使用浮动定位方案,元素 CSS 属性position 为 static
或 relative
,而后float
不为none
。若是 float
设为 left
, 浮动由行盒的开头开始定位。若是设为 right
, 浮动定位在行盒的末尾。
对于绝对定位方案, 盒从常规流中被移除,不影响常规流的布局。 它的定位相对于它的包含块,相关CSS属性:top, bottom, left及right 。
若是元素的属性position为 absolute
或 fixed, 它是绝对定位元素。
固定定位元素(fixed positioned element)也是绝对定位元素,它的包含块是视口。当页面滚动时它固定在屏幕上,由于视口没有移动。
以上。