在普通流中,元素按照其在 HTML 中的前后位置至上而下布局,在这个过程当中,行内元素水平排列,直到当行被占满而后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,不然全部元素默认都是普通流定位,也能够说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。css
在浮动布局中,元素首先按照普通流的位置出现,而后根据浮动的方向尽量的向左边或右边偏移,其效果与印刷排版中的文本环绕类似html
在绝对定位布局中(position值为absolute或fixed),元素会总体脱离普通流,所以绝对定位元素不会对其兄弟元素形成影响,而元素具体的位置由绝对定位的坐标决定。git
Formatting context(格式化上下文) 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,而且有一套渲染规则,它决定了其子元素将如何定位,以及和其余元素的关系和相互做用。github
格式化上下文有如下几种类型:segmentfault
一个页面是由不少个Box
组成的,元素的类型和display
属性决定了这个Box
的类型。不一样类型的 Box,会参与不一样的 Formatting Context。Block level
的box会参与造成BFC,好比display
值为block,list-item,table
的元素。Inline level
的box会参与造成IFC,好比display
值为inline,inline-table,inline-block
的元素。ide
块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其余元素交互的区域。(我的理解:BFC布局方式和上述普通流布局方式类似)布局
具备 BFC 特性的元素能够看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,而且 BFC 具备普通容器所没有的一些特性。flex
下列方式会建立块级格式化上下文:ui
<html>
)float
不是 none
)position
为 absolute
或 fixed
)display
为 inline-block
)display
为 table-cell
,HTML表格单元格默认为该值)display
为 table-caption
,HTML表格标题默认为该值)display
为 table、
`table-row、
table-row-group、table-header-group、
table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或
inline-table`)overflow
值不为 visible
的块元素display
值为 flow-root 的元素contain
值为 layout
、content
或paint 的元素display
为 flex
或 inline-flex
元素的直接子元素)display
为 grid
或 inline-grid
元素的直接子元素)column-count
或 column-width
不为 auto,包括
`column-count 为
1`)column-span
为 all
的元素始终会建立一个新的BFC,即便该元素没有包裹在一个多列容器中(标准变动,Chrome bug)。块格式化上下文包含建立它的元素内部的全部内容.spa
margin
决定。属于同一个BFC的两个相邻Box的margin
会发生重叠margin-left
), 与包含块的左边(contain box left
)相接触(对于从左往右的格式化,不然相反)。即便存在浮动也是如此。除非这个元素本身造成了一个新的BFC。float box
重叠。浮动的元素会脱离普通文档流
<div style="border: 1px solid #000;"> <div style="width: 100px;height: 100px;background: #eee;float: left;"></div> </div>
因为容器内元素浮动,脱离了文档流,因此容器只剩下 2px 的边距高度。若是使触发容器的 BFC,那么容器将会包裹着浮动元素。
效果如图:
先来看一个文字环绕效果:
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一个左浮动的元素</div> <div style="width: 200px; height: 200px;background: #eee">我是一个没有设置浮动, 也没有触发 BFC 元素, width: 200px; height:200px; background: #eee;</div>
这时候其实第二个元素有部分被浮动元素所覆盖,(可是文本信息不会被浮动元素所覆盖) 若是想避免元素被覆盖,可触第二个元素的 BFC 特性,在第二个元素中加入overflow: hidden,就会变成:
这个方法能够用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度(去掉上面右边内容的宽度)。
<head> div{ width: 100px; height: 100px; background: lightblue; margin: 100px; } </head> <body> <div></div> <div></div> </body>
从效果上看,由于两个 div 元素都处于同一个 BFC 容器下 (这里指 body 元素) 因此第一个 div 的下边距和第二个 div 的上边距发生了重叠,因此两个盒子之间距离只有 100px,而不是 200px。
首先这不是 CSS 的 bug,咱们能够理解为一种规范,若是想要避免外边距的重叠,能够将其放在不一样的 BFC 容器中。
<div class="container"> <p></p> </div> <div class="container"> <p></p> </div>
.container { overflow: hidden; } p { width: 100px; height: 100px; background: lightblue; margin: 100px; }
这时候,两个盒子边距就变成了 200px
<style> .box{ width:100px; height:100px; background:#ccc; } .wrap { background:yellow; } .wrap h1{ background:pink; margin:40px; } </style> <body> <div class="box">box</div> <div class="wrap"> <h1>h1</h1> </div> </body>
上图wrap元素与h1元素之间l理论上本该有个40px的上下margin值,然而实际上父子元素并无存在margin值,与此同时,两个div元素的间距为40px。遇到这种情形,咱们如何处理?
处理方法其实有不少,在wrap元素中添加:overflow:hidden;或者overflow:auto;使其父元素造成一个BFC;也能够在wrap元素中添加border:1px solid;或是padding:1px;这些均可以有效解决父子元素margin重叠问题。
IFC(Inline Formatting Contexts)直译为"内联格式化上下文",IFC的line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)。
IFC中框模型不彻底适用于参与内联格式上下文的项。在水平书写模式行中,水平填充、边框和边距将应用于元素,并左右推送文本。可是,不会应用元素上下的边距。将应用垂直填充和边框,但可能会在内容的上方和下方重叠,由于在内联格式上下文中,填充和边框不会将行框推开。
在行内格式化上下文中,框(boxes)一个接一个地水平排列,起点是包含块的顶部。水平方向上的margin
,border
和padding
在框之间获得保留。框在垂直方向上能够以不一样的方式对齐:它们的顶部或底部对齐,或根据其中文字的基线对齐。包含那些框的长方形区域,会造成一行,叫作行框。
当一个块要在环境中水平居中时,设置其为inline-block则会在外层产生IFC,经过text-align则可使其水平居中。
建立一个IFC,用其中一个元素撑开父元素的高度,而后设置其vertical-align:middle,其余行内元素则能够在此父元素下垂直居中。
GFC(GridLayout Formatting Contexts)直译为"网格布局格式化上下文",当为一个元素设置display值为grid的时候,此元素将会得到一个独立的渲染区域,咱们能够经过在网格容器(grid container)上定义网格定义行(grid definition rows)和网格定义列(grid definition columns)属性各在网格项目(grid item)上定义网格行(grid row)和网格列(grid columns)为每个网格项目(grid item)定义位置和空间。
GFC将改变传统的布局模式,他将让布局从一维布局变成了二维布局。简单的说,有了GFC以后,布局再也不局限于单个维度了。这个时候你要实现相似九宫格,拼图之类的布局效果显得格外的容易。
FFC(Flex Formatting Contexts)直译为"自适应格式化上下文",display值为flex或者inline-flex的元素将会生成自适应容器(flex container)。
Flex Box 由伸缩容器和伸缩项目组成。经过设置元素的 display 属性为 flex 或 inline-flex 能够获得一个伸缩容器。设置为 flex 的容器被渲染为一个块级元素,而设置为 inline-flex 的容器则渲染为一个行内元素。
伸缩容器中的每个子元素都是一个伸缩项目。伸缩项目能够是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。简单地说,Flexbox 定义了伸缩容器内伸缩项目该如何布局。
总体来讲,FFC与BFC有点儿相似,但仍有如下几点区别:
https://developer.mozilla.org...
https://developer.mozilla.org...
https://segmentfault.com/a/11...
https://zhuanlan.zhihu.com/p/...