CSS - 包含块

193 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第28天,点击查看活动详情

我正在参加 码上掘金体验活动,详情:show出你的创意代码块

一个元素的尺寸和位置经常受其包含块(containing block)的影响。

一般情况下,包含块就是这个元素最近的祖先块级元素的内容区或最近的开启BFC的祖先元素的内容区,但也不是总是这样

当一个客户端代理(比如说浏览器)展示一个文档的时候,对于每一个元素,它都产生了一个盒子。

每一个盒子都被划分为四个区域:

  1. 内容区
  2. 内边距区
  3. 边框区
  4. 外边距区

包含块的确定

元素分类包含块
标准流中布局的元素或定位值为relative或sticky的定位元素最近的祖先元素的内容区或最近的开启BFC的元素的内容区
position的值为absolute的定位元素最近的那个定位祖先元素
position的值为fixed的定位元素视口
对于绝对定位元素
(也就是position的值为fixed或absolute的定位元素)
可以是最近的那个transformperspective的值不为none的祖先元素

根元素(<html>)所在的包含块是一个被称为初始包含块的矩形, 其本质上就是视口(viewport)

包括块的作用

  1. 我们在设置元素的width, height, margin, padding, top, bottom, left, right的值为百分比的时候,所参照的对应值就是由这个元素的包含块计算而来的
  2. 产生定位的元素,也是参照其对应的包含块的
属性参照
height, top, bottom包含块的 height
如果包含块的height为auto,且包含块没有脱标,那么这些值的计算值为auto,表现为0
width, margin, padding, left, right包含块的 width
margin和padding四个方向的值其在设置百分比的时候,其实参照包含块的width

示例

  1. 在标准流中,普通元素的包含块就是其父元素
.container {
  width: 300px;
  height: 300px;
  background-color: skyblue;
}

/* div.box的包含块为div.container */
.box {
  /* 300 * 50% = 150px */
  width: 50%;
  /* 300 * 50% = 150px */
  height: 50%;
  /* 300 * 10% = 30px */
  margin: 10%;
  /* 300 * 10% = 30px */
  padding: 10%;
  background-color: gray;
}

掘金代码片段

  1. 只有块级元素或开启了BFC的元素,才可能形成包含块
.container {
  display: inline;
  width: 300px;
  height: 300px;
  background-color: skyblue;
}

/* 此时div.box的父元素不是一个块级元素,所以其包含块是viewport */
.box {
  /* width of viewport * 50% */
  width: 50%;
  /*
    viewport的宽度是由div.box撑开的
    所以height的值为auto,表现为0
  */
  height: 50%;
  /* width of viewport * 10%  */
  margin: 10%;
  /* width of viewport * 10% */
  padding: 10%;
  background-color: gray;
}

掘金代码片段

  1. 如果包含块是content-box,其宽高会受其padding和border的影响

​ 但是如果包含块是border-box, 就不会存在这个问题

.outter {
  /*
  此时因为存在padding
  所以div.outter变成了 640 * 640的容器
  */
  position: absolute;
  width: 600px;
  height: 600px;
  padding: 20px;
  background-color: purple;
}

.container {
  width: 300px;
  height: 300px;
  background-color: skyblue;
}

.box {
  position: absolute;
  /* 640 * 50% = 320 */
  width: 50%;
  /* 640 * 50% = 320 */
  height: 50%;
  /* 640 * 10% = 64 */
  margin: 10%;
  /* 640 * 10% = 64 */
  padding: 10%;
  /* 640 * 10% = 64 */
  left: 10%;
  /* 640 * 10% = 64 */
  top: 10%;
  background-color: gray;
}

掘金代码片段

.outter {
  /*
  如果父元素是border-box, 那么其实际的宽度和高度就不会被padding或border给撑开了
  在这里,其实际宽度就是600 * 600
  */
  box-sizing: border-box;
  position: absolute;
  width: 600px;
  height: 600px;
  padding: 20px;
  background-color: purple;
}

.container {
  width: 300px;
  height: 300px;
  background-color: skyblue;
}

/* div.box的包含块为 div.outter */
.box {
  position: absolute;
  /* 600px * 50% = 300px */
  width: 50%;
  /* 600px * 50% = 300px */
  height: 50%;
  /* 600px * 10% = 60px */
  margin: 10%;
  /* 600px * 10% = 60px */
  padding: 10%;
  /* 600px * 10% = 60px */
  left: 10%;
  /* 600px * 10% = 60px */
  top: 10%;
  background-color: gray;
}

掘金代码片段

  1. 固定定位元素是相对于其包含块的,而默认包含块为viewport
.outter {
  transform: scale(1);
  width: 600px;
  height: 600px;
  padding: 20px;
  background-color: purple;
}

.container {
  width: 300px;
  height: 300px;
  background-color: skyblue;
}

.box {
  /*
    当元素是绝对定位元素
    也就是position属性值为fixed或absolute的时候

    对于absolute元素,其包含块就是最近的那个定位祖先元素,
    或者是transform值不为none或prespective的值不为none的那个祖先元素

    对于fixed元素,其包含块就是viewport,
    或者是transform值不为none或prespective的值不为none的那个祖先元素

    所以在这里 div.box的包含块是参照于div.outter
    此时div.box的定位也是参照于div.outter的,不再是viewport
  */
  position: fixed;
  width: 50%;
  height: 50%;
  margin: 10%;
  padding: 10%;
  left: 10%;
  top: 10%;
  background-color: gray;
}

掘金代码片段