标准文档流
标准文档流 指的是元素排版布局过程中,元素会默认自动从左往右,从上往下的 流式排列方式 。并最终窗体自上而下分成一行行,并在每行中从左至右的顺序排放元素。
布局的方式
-
盒子内部的布局
- 文本的布局
- 盒子本身的布局
-
盒子之间的布局
-
脱离标准文档流下的盒子的布局
- 定位布局
- 浮动布局
-
标准文档流下的盒子的布局
- 块级格式化上下文(
Block Formatting Context) - 行内格式化上下文(
Inline formatting contexts) - 自适应格式化上下文(
Flex Formatting Contexts) - 网格布局格式化上下文(
GridLayout Formatting Context) - 表格布局上下文(
Table Formatting Context)
- 块级格式化上下文(
-
盒子内部的布局
文本的布局
- 存在一个看不见的
line boxes包裹每行文字。 line boxes的高度取决于line-height。- 通过
line-height可以设置单行文本的垂直居中。
盒子本身的布局
盒子由内容(content)、内边距(padding)、边框(border)、外边距(margin)构成。
盒模型有两种标准,一个是标准盒模型,一个是 IE 盒模型。
浮动布局
什么是浮动布局:
所谓 css 浮动就是浮动元素会脱离文档的普通流,根据 float 的值向左或向右移动,直到它的外边界碰到父元素的内边界或另一个浮动元素的外边界为止。
请看下图,当把框 1 向右浮动时,它脱离文档流并且向右移动,直到它的右边缘碰到包含框的右边缘。
浮动布局的生成:
css 属性 float:left/right/none 左浮动/右浮动/不浮动(默认)。
浮动的影响:
- 不会影响未浮动的块级元素布局,但会影响内联元素的布局。
- 浮动后的元素可以设置宽度和高度,也就是说内联元素浮动后会变成块级元素。
- 因为浮动元素脱离了普通流,会出现一种高度坍塌的现象:原来的父容器高度是当前盒子撑开的,但是当当前盒子浮动后,脱离文档流浮动起来,那父容器的高度就坍塌。
- 元素浮动之后,会让它跳出文档流,也就是说当它后面还有元素时,其他元素会无视它所占据了的区域,直接在它身下布局。但是文字、图片、表单标签依然会为这个标签让出位置,会认同浮动元素所占据的区域,围绕它布局,也就是没有脱离文本流。
定位布局
什么是定位布局:
标准文档流和浮动布局都只能在水平或垂直方向布局元素,但现实是,我们可能需要在上下左右几个方向上同时偏移元素,定位布局正是为了解决这一问题而设计的。
定位布局的生成:
通过设置元素的 position 属性,可以让元素处于定位布局中,并通过 left、right、top、bottom 属性设置元素具体的偏移量。
定位布局分为四种:
static静态定位,实际上所有元素默认都是静态定位的,即处于标准流中。relative相对定位,元素保留在标准流中所占用的位置,但实际是边框及以内的部分将显示在偏移之后的位置。在相对定位中,实际上元素并未脱离标准流,所以浏览器还是会区分它是否是块级或其他类型的元素。另外,设置元素的margin属性,实际上margin区域会出现在元素定位之前的位置。absolute绝对定位,元素脱离标准流,浏览器把它视作块级元素,不论定位之前它是何种元素,其他元素也将无视它。绝对定位的偏移量是相对于其有定位属性的第一个祖先元素的,另外,绝对定位的元素会自动忽略有定位属性的祖先元素的padding属性。fixed固定定位,固定定位和绝对定位相似,但它的偏移量固定的相对于浏览器窗口,它会脱离标准文档流,并且浏览器把他们一致视作块级元素。
通常情况下,元素的 z-index 属性值都是 0 ,并且定位布局中的元素会覆盖标准流中的元素,同在定位布局中的元素,写在后面的会覆盖写在前面的元素。在定位布局中,可以设置它们的 z-index 属性来调整它们的覆盖关系,并且谁的值越大,显示优先级越高。如果定位元素的父元素也设置了 z-index 属性,那么子元素的 z-index 属性将失效,并且最终是根据父元素的 z-index 属性来判断覆盖关系。
格式上下文
Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,有一套渲染规则决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
块级格式化上下文
BFC( Block Formatting Context )
BFC是一个独立的区域,它内部的元素都依照它的规则渲染,并且不会与BFC外部打交道。
以下方式会创建 BFC:
- 根元素或包含根元素的元素
- 浮动元素(元素的 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或 strict 的元素
- 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
- 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
- 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
- column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中
当一个元素设置了新的 BFC 后,就和这个元素外部的 BFC 没有关系了,这个元素只会去约束自己内部的子元素。
BFC 的布局规则例如以下:
- 内部的盒子会在垂直方向,一个个地放置;
- 盒子垂直方向的距离由
margin决定,属于同一个BFC的两个相邻Box的上下margin会发生重叠; - 每一个元素的左边,与包含块的左边相接触(对于从右往左的布局,则相反),即使存在浮动也是如此;
BFC的区域不会与float重叠;BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此;- 计算
BFC的高度时,浮动元素也參与计算。
行内格式化上下文
IFC( Inline formatting contexts )
以下方式会创建 IFC:
- 块级元素中仅包含内联级别元素。
IFC 的布局规则例如以下:
- 内部的盒子会在水平方向,一个个地放置,水平的外边距,内边距,边框是可以有的;
IFC的高度,由里面最高盒子的高度决定;- 当一行不够放置的时候会自动切换到下一行;
- 根据
vertical-align属性垂直对齐,可能是底部对齐,顶部对齐,也可能是基线对齐(默认); - 是当
IFC中有块级元素插入时,会产生两个匿名块将父元素分割开来,产生两个IFC; - 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(
line box)。行框的宽度是由包含块和与其中的浮动来决定; IFC中的行框一般左右边贴紧其包含块,但float元素会优先排列;IFC中的行框高度由CSS行高计算规则来确定,同个IFC下的多个行框高度可能会不同;- 当
IFC中盒子的总宽度少于包含它们的行框时,其水平渲染规则由text-align属性值来决定; - 当一个行内元素超过父元素的宽度时,它会被分割成多个盒子,这些盒子分布在多个行框中。如果子元素未设置强制换行的情况下,行框将不可被分割,将会溢出父元素。
自适应格式化上下文
FFC( Flex Formatting Contexts ),display 值为 flex 或者 inline-flex 的元素将会生成自适应容器。flex box 由伸缩容器和伸缩子元素组成。通过设置元素 display:flex/inline-flex 可以得到伸缩容器,前者为块级元素,后者为行内元素。伸缩容器外元素不受影响。
网格布局格式化上下文
GFC( GridLayout Formatting Contexts ),当一个元素设置为 display:grid 的时候,此元素将获得一个独立的渲染区域,可以在网格容器上定义网格行和列,为每一个网格定义位置和空间。GFC 和 table 的区别在于 GridLayout 会有更加丰富的属性来控制行列,控制对齐以及更为精细的渲染。
表格布局上下文
随着各种技术的不断发展,table 布局已经逐渐退出了历史的舞台,但是因为 table 本身的一些特性,比如上下对齐,左右对齐,文字默认居中使得 table 在曾经的布局中占有一席地位。
<style>
.left {
background: red;
}
.right {
background: blue;
}
table {
width: 800px;
height: 200px;
border-collapse: collapse;
}
</style>
<body>
<table>
<tr>
<td class="left">左</td>
<td class="right">右</td>
</tr>
</table>
</body>