大家都不看的总集篇: 从零开始的大前端筑基之旅(深刻浅出,持续更新~)
以为不错就顺手点个赞吧~css
划重点: 本文全部示例均为手打html示例,能够直接选中示例在控制台调试,方便验证各类想法。手敲不易,若是你以为示例调试方便,那我在此求个赞~html
外边距重叠就是 margin-collapse
。相邻的两个盒子(多是兄弟关系也多是祖先关系)的外边距能够结合成一个单独的外边距。 这种合并外边距的方式被称为折叠,结合而成的外边距称为折叠外边距。前端
折叠结果遵循下列计算原则:react
有些人看到这里可能会想:啊,我作列表的时候遇到过这种状况,折腾了我半天呢。webpack
另外一些人可能会想:这是什么玩意,我怎么没遇到过?这难道不是css的bug么?css3
咱们先来讲说什么状况下不会产生外边距重叠web
等等,先不要列举了,这些条件怎么看着那么眼熟呢?嗯。。。这不就是生成BFC的条件么。。。。typescript
BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,而且与这个区域外部绝不相干。segmentfault
咱们常说的文档流其实分为定位流、浮动流、普通流三种。而普通流其实就是指BFC中的FC。FC(Formatting Context),直译过来是格式化上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其余元素之间的关系和做用。babel
先介绍下Box、Formatting Context的概念。
Box:css布局的基本单位
Box 是 CSS 布局的对象和基本单位, 直观点来讲,就是一个页面是由不少个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不一样类型的 Box, 会参与不一样的 Formatting Context(一个决定如何渲染文档的容器),所以Box内的元素会以不一样的方式渲染。
block-level box:display
属性为 block, list-item, table 的元素,会生成 block-level box。而且参与 block fomatting context;inline-level box:display
属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。而且参与 inline formatting context;run-in box
: css3 中才有, 这儿先不讲了。Formatting Context
Formatting context
是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,而且有一套渲染规则,它决定了其子元素将如何定位,以及和其余元素的关系和相互做用。最多见的 Formatting context
有 Block fomatting context
(简称BFC)和 Inline formatting context
(简称IFC)。
具备 BFC 特性的元素能够看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,而且 BFC 具备普通容器所没有的一些特性。
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。
每一个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,不然相反)。即便存在浮动也是如此。即BFC中子元素不会超出他的包含块。
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算。
display: table
也能够生成BFC的缘由在于Table会默认生成一个匿名的table-cell,是这个匿名的table-cell生成了BFC。BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然。咱们能够利用BFC的这个特性来作不少事。
<div class="container">
<div class="inner"></div>
<div class="inner"></div>
</div>
复制代码
.container{
display: inline-block;
border: 1px solid grey;
}
.inner{
width: 20px;
height: 20px;
margin: 20px;
border: 1px solid grey;
background: lightblue;
}
复制代码
从效果上看,由于两个 div 元素都处于同一个 BFC 容器下 (这里经过设置container
为 display: inline-block
) 因此第一个 div 的下边距和第二个 div 的上边距发生了重叠,因此两个盒子之间距离只有 20px,而不是 40px。
首先这不是 CSS 的 bug,咱们能够理解为一种规范,若是想要避免外边距的重叠,能够将其放在不一样的 BFC 容器中。
<div class="container">
<div class="inner"></div>
<div class="container1">
<div class="inner"></div>
</div>
</div>
复制代码
.container{
display: inline-block;
border: 1px solid grey;
}
.container1{
display: inline-block;
}
.inner{
width: 20px;
height: 40px;
margin: 40px;
border: 1px solid grey;
background: orange;
overflow: hidden;
}
复制代码
这里,将第二个div
放进container1
中,经过设置container
为 display: inline-block
使其产生BFC,这样,两个inner
就在不一样的BFC下,边距就不会重叠。两个盒子之间距离是 40px。
ps:此样例使用html编写,可直接点击示例在控制台调试,试试取消container1
的style以后的效果吧
浮动的元素会脱离普通文档流,来看下下面一个例子
<div class="container">
<div class="inner"></div>
</div>
复制代码
.container{
border: 1px solid grey;
}
.inner{
width: 20px;
height: 20px;
margin: 20px;
background: orange;
float: left;
}
复制代码
栗子,包括下面的横线
因为容器内元素浮动,脱离了文档流,因此容器只剩下 2px 的边距高度。若是使触发容器的 BFC,那么容器将会包裹着浮动元素。
经过overflow: hidden
使container
生成BFC
.container{
border: 1px solid grey;
overflow: hidden;
}
复制代码
本例也能够直接点击调试哦~
你真的清楚浮动效果么?告诉你个浮动的隐藏效果,做为交换,你给我点个赞,咋样
解释这个做用以前,我先来解释一下什么是浮动
什么是浮动
元素加了浮动后,会脱离文档流,提高了半层层级,向着指定方向移动,直到遇到父元素的边界或另外一个浮动元素中止
什么是层级
若是将整个元素看作一层,则下半层是元素自己(背景样式等),上半层是元素中的内容
举例
<div class="container">
<div class="box1">box1</div>
<div class="box2">box2</div>
<div class="box3">box3</div>
</div>
复制代码
.container{
width: 40px;
border: 1px solid black;
}
.container div{
width: 100%;
height: 30px;
}
.box1 {
background: yellow;
}
.box2 {
background: orange;
}
.box3 {
background: pink;
}
复制代码
三个盒子都没有浮动时
当给box2添加float:left时,三个盒子的排列变成
此时因为box2浮动脱离了文档流,box3上移,被box2遮挡了。但此时box3盒子里的文字box3并无上移!!!
小知识
position:absolute
和float
会隐式地改变display
类型,除display:none
外,只要设置了position:absolute
或float
,都会让元素以display:inline-block
的方式显示,能够设置长宽浮动效果讲完了,咱们来看看元素被浮动元素覆盖的例子
<div class="container">
<div class="left">我是一个左浮动的元素</div>
<div class="right">我是一个没有设置浮动,
也没有触发 BFC 的元素, 个人一部分被覆盖了</div>
</div>
复制代码
.left{
width: 100px;
height: 50px;
background: orange;
float: left;
}
.right{
width: 200px;
height: 200px;
background: lightblue;
}
复制代码
第二个元素有部分被浮动元素所覆盖,(可是文本信息不会被浮动元素所覆盖,缘由在上面浮动例子解释过) 若是想避免元素被覆盖,可触第二个元素的 BFC 特性,在第二个元素中加入 overflow: hidden,就会变成:
这个方法能够用来实现两列自适应布局,经过设置container
的宽度,去掉right
的宽度便可。这时候左边的宽度固定,右边的内容自适应宽度。
Ps: 建议在控制台调试一下本示例
ps:我通常使用display: flex
,而后左侧宽度固定,右侧设置flex: 1
,这个方法垂直方向也可使用,我经常使用来设置滚动列表的高度,这个方法也能够实现动态宽度的布局
例子以下:
<div class="container">
<div class="left">左侧元素,定宽</div>
<div class="right">右侧元素,动态填充剩余空间</div>
</div>
复制代码
.container{
width: 400px;
display: flex;
border: 1px solid grey;
}
.left{
width: 100px;
height: 50px;
background: orange;
}
.right{
height: 200px;
flex: 1;
background: lightblue;
}
复制代码
你能够在控制台调整一下container
的宽度,右侧元素会自动填充
讲完了BFC及其做用,除了最直观的,同一个 BFC 下外边距会发生折叠,咱们来看下其余边距重叠的示例
栗子以下:
<div class="container">
<div class="title">
此部分是能更容易看出让下面的块的margin-top。
</div>
<div class = "content">
<div class="inner">
子元素
margin-top:20px;
</div>
<h2>父元素</h2>
没有设置margin-top
</div>
</div>
复制代码
.container{
width: 400px;
border: 1px solid grey;
}
.title{
height:50px;
background: #eee;
}
.content{
height:200px;
background: #88f;
}
.inner{
height:100px;
margin-top:20px;
background: #0ff;
width:200px;
}
复制代码
父元素和子元素margin-top发生了重叠,最终结果至关于父元素设置了20px的margin-top。
能够设置 overflow:hidden
来解决这个问题。你能够选中示例在控制台本身尝试一下其余解决方案。
<div class="container">
<div class="inner"></div>
</div>
复制代码
.container{
width: 200px;
border: 1px solid grey;
}
.inner{
margin-top:20px;
margin-bottom: 20px;
}
复制代码
这个框的高度只有20px,稍微改动下inner元素,好比加个文字,或者加个边框,都会破坏这种现象,欢迎本身打开控制台尝试一下各类解决方案。
好了,外边距重叠、BFC、及浮动的讲解到此结束。有任何想法和意见欢迎在评论中指出。若是你收获了新知识,请点个赞告诉我~
本文收纳于: 从零开始的大前端筑基之旅(深刻浅出,持续更新~)
推荐阅读:
带你撸个属于本身的react项目|webpack+babel+typescript+eslint
没搭过项目的新人必定不容错过,带你解锁快捷开发小技巧
三言两语带你理解「闭包」| 附使用场景
很简单就能解释清的东西为何要多费口舌呢?
朝花夕拾,从新介绍继承与原型链
有图有真相的讲解
回流(reflow)与重绘(repaint),KFC与MC
每次这两个都会被同时说起,关系就好像KFC边上必定会有MC同样亲密的让人摸不到头脑。
viewport和1px | 工具人: 这是1px,设计师: 不,这不是
设计我不行,但吵架我在行啊
可食用的「css布局干货」,纯Html示例,可调试 | 水平、垂直、多列
可观看,可调试,可带走,仅此一家,别无分店
前端必须掌握的「CSS层叠上下文」讲解 | 纯手工示例,包教包会
妹子与猫,你要哪一个?
参考文档: