CSS:盒模型总结梳理

1,176 阅读6分钟
盒模型

在css中,任何元素都可以看成是一个盒子。一个盒子是由四部分组成的:内容(content)、内边框(padding)、边框(border)和外边框(margin)。

盒模型有两种:标准盒模型IE盒模型。分别是有W3C和IExplore制定的标准。例如:

.box {
    width: 200px;
    height: 200px;
    padding: 10px;
    border: 1px solid #eee;
    margin: 10px;
}

标准盒模型下,盒子的实际尺寸:内容(设置的宽/高)+ 内边距 + 边框。即:size=200+10+10+1+1=222px。

IE盒模型下,盒子的实际尺寸=设置的宽/高= 内容 + 内边距 + 边框。即:内容=200-10-10-1-1=178px。

现在高版本的浏览器基本上默认都是使用的标准盒模型,而像IE6这种老古董才是默认使用的IE盒模型。

在CSS3中新增了一个属性box-sizing,可以指定盒子使用什么标准,有两个值:content-box:标准盒模型border-box:IE盒模型

视觉格式化模型

视觉格式化模型是用来处理在视觉媒体上显示文档时使用的计算规则。CSS中一切皆盒子,而视觉格式化模型简单来理解就是规定这些盒子应该以怎样的方式放置到页面中去。视觉格式化模型在计算的时候会依赖很多因素,比如:盒子尺寸、盒子类型、定位方案(浮动或定位)、兄弟元素或子元素等。

我们都知道,盒子类型是由display决定的,给元素设置display后,会决定这个盒子的两个显示类型:

  • 对外显示:决定了该元素本身是如何布局的,即自身参与何种格式化上下文。
  • 对内显示:即把当前元素当作一个容器,规定了容器内的子元素是如何布局的、参与何种格式化上下文。
对外显示

在对外显示方面,盒子类型可以分成两类:块级盒子和行内盒子。

  • 块级盒子:通过设置display为block、list-item、table、flex、grid、flow-root等。参与BFC,呈现垂直排列。
  • 行内盒子:通过设置display为inline、inline-block、inline-table等。参与IFC,呈现水平排列。
对内显示

在对内显示方面,盒子类型根据display的值不同,可以构建四种格式化上下文:

  • Block container:建立BFC或者IFC
  • Flex container:建立FFC
  • Grid container:建立GFC
  • Ruby container:接触不多。。。
文档流

文档流就是css会把html文档内容从左到右,从上到下依次排列显示。能够自适应所在的容器。一般分两类元素,块元素默认会占据一行显示,所以多个块元素是上下排列的。行内元素是从左到右同行排列,直到占满一行再自动换行显示。

如何脱离文档流

某元素一旦脱离文档流,其正常所在的位置会被后续节点所填补,也就是脱离文档流的元素不占据空间。并且脱离文档流的元素,不纳入其父节点高度的计算,所以会影响其父节点高度。一般有两种方式可以使元素脱离文档流:浮动和定位。

浮动:使用float,可以使元素移动到容器的左/右侧,或是另一个浮动元素旁边。需要注意的是,盒模型脱离文档流后,但没有脱离文本流,这也是呈现文字环绕效果的原因。

定位:使用绝对定位 position:absolute 或者固定定位 position:fixed 也可以使元素脱离文档流,而且空出来的位置将自动被后续节点填充。这种方式即脱离文档流也脱离文本流,所以以定位的方式脱离文档流后,其后的元素或文本都会占据该元素原来的位置,也就是会被定位元素覆盖。

BFC(块级格式化上下文)

BFC代表的是一块独立的渲染区域,可以把BFC理解成元素的一种特性,当元素拥有了BFC特性后,这个元素就可以看成是一个独立的容器,容器内的元素不会影响外部元素。

BFC渲染规则
  • BFC容器内部的块级盒子会在垂直方向一个接一个的放置;
  • BFC容器内,块级盒子垂直方向上的距离由margin决定。同属于一个BFC容器内的两个相邻块级盒子的margin会发生合并,不属于同一个BFC容器的两个相邻块级盒子不会发生margin合并;
  • BFC容器内,每个元素的左外边框和容器的左边界接触,即容器内部的元素不会超出容器左右侧区域,内部浮动元素也是如此;
  • BFC容器不会与浮动元素重叠(两栏布局原理);
  • 计算BFC容器的高度时,内部的浮动元素也参与计算(解决父元素高度塌陷原理)。
如何创建BFC
  • 根元素html,即<html></html>是BFC容器;
  • 设置浮动,float属性值不为none;
  • 为元素设置overflow属性,值不为visible(可选值:auto、scroll、hidden);
  • 设置定位,position值为absolute或fixed;
  • 行内块元素,即display属性值为inline-block;
  • 弹性元素,即display为 flex 或 inline-flex元素的直接子元素;
  • 网格元素,即display为 grid 或 inline-grid 元素的直接子元素;
  • 表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值);
  • 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值);
BFC应用场景

1、自适应两栏布局

应用原理:BFC 的区域不会和浮动区域重叠,所以就可以把侧边栏固定宽度且左浮动,而对右侧内容触发 BFC,使得它的宽度自适应该行剩余宽度。

<div class="layout">
    <div class="aside">aside</div>
    <div class="main">main</div>
</div><style>
  .aside {
    float: left;
    width: 100px;
  }
  .main {
      <!-- 触发 BFC -->
      overflow: auto;
  }
</style>

2、清除浮动

浮动造成的问题主要是父元素高度坍塌,所以清除浮动需要解决的问题就是让父元素的高度恢复正常。而用 BFC 清除浮动的原理就是:计算 BFC 的高度时,浮动元素也参与计算。只要触发父元素的 BFC 即可。

.parent {
    overflow: hidden;
}

3、防止垂直 margin 合并

外边距折叠:在CSS中,两个或多个毗邻的普通流中的盒子(可能是父子元素,也可能是兄弟元素)在垂直方向上的外边距会发生叠加,这种形成的外边距称之为外边距叠加。

BFC 渲染原理中,同一个 BFC 容器下的垂直 margin 会发生合并。所以如果让 2 个元素不在同一个 BFC 中即可阻止垂直 margin 合并。那如何让 2 个相邻的兄弟元素不在同一个 BFC 中呢?可以给其中一个元素外面包裹一层,然后触发其包裹层的 BFC,这样一来 2 个元素就不会在同一个 BFC 中了。

<div class="layout">
    <div class="a">a</div>
    <div class="contain-b">
        <div class="b">b</div>
    </div>
</div><style>
  .demo3 .a,
  .demo3 .b {
      border: 1px solid #999;
      margin: 10px;
  }
  .contain-b {
      overflow: hidden;
  }
</style>
总结

本篇总结梳理了盒模型、文档流、BFC等知识。如有错漏,欢迎指正讨论!!!