什么是containing block?

如果干巴巴的问一个前端什么是containing block。大部分都不知所云。官方示意如下:

The size and position of an element are often impacted by its containing block. Most often, the containing block is the content area of an element’s nearest block-level ancestor, but this is not always the case. In this article, we examine the factors that deterime an element’s containing block.

简单来说就是——无特殊情况下,containing block(包含块)就是最近的块元素的content area(内容区)

什么是内容区?

以这个经典的盒模型图:

最内部的即为内容区。

border-box

有两种盒子模型:

①是标准盒子模型,一般浏览器默认为标准盒子模型。即:box-sizing:content-box

  • 没有设置box-sizing:border-box属性,宽高就是设置的宽度和高度,展示在页面上的宽高会加上padding和border的值
  • 比如填满宽度的时候直接写width:100%,这时候如果有padding和border,页面会被撑开,出现滚动条

②是怪异盒子模型,可根据实际项目需要自行设置。即:box-sizing:border-box

  • 加了box-sizing:border-box属性,padding和border的值都算在设置的width和height数值里面,一些老司机可能喜欢这个
  • 比如填满宽度的时候,可以直接写width:100%

我们平时用到过吗?

这个概念虽然可能不熟悉,但是实际上我们经常用到:

.outer {
    width: 200px;
    box-sizing: border-box;
}
.inner {
    width: 80%;
}

inner的宽度是多少呢?毫无疑问,是160px。那稍微加一点戏,如果outer增加一条属性padding: 50px,这时候inner的宽度是多少?

很多人会迟疑一下,因为不知道背后的原理,只能根据经验推断,如果经验老道,会给出正确答案:80px

实际上,这些百分比值的运作原理都是通过包含块来计算出最后结果。再回想一下之前的规范,包含块通常是最近的块元素的内容区,就可以很清晰的理解padding值在这个例子中起的作用了。

元素的尺寸和位置经常受其包含块的影响。

特殊情况

如果敏感的人看到这可能会产生一个疑惑,如果把例子改成这样?

.outer {
    position: relative;
    width: 200px;
    padding: 50px;
    box-sizing: border-box;
}
.inner {
    position: absolute;
    width: 80%;
}

这时候inner width又是多少呢?是160px。好不容易刚消化的知识就给了当头一棍。。。然后回想一下平时用的时候好像确实是这样!

所以规范提到了无特殊情况下,而特殊情况是:

  • 如果position是absolute,包含块就是它最近的position值不是static的元素的padding area
  • 如果position是fixed,包含块就是视图,就是整个view可视范围视窗。
  • 如果position是absolutefixed,包含块是最近的满足下列条件的元素的padding area
    • transform或perspective值不是none
    • filter值不是none
    • will change值包含transform、perspective、或filter(只有Firefox有效)

position: fixed

了解了包含块的规范,可以更好的理解平时常用的一些特性的运行原理。而特殊情况的最后一点,其实还有一些场景可以利用。

比如如下场景:

引入了一个三方ui库,内部有一个弹窗组件,很正常的使用了fixed定位,那它的包含块就是视图了。如果这时,需要将它的位置进行调整,那怎么办?

可以利用transform/perspective/filter来改变这个弹窗所在的内容块,从而起到定位的作用。

contain

理解了包含块,能够将特性运用到一些特定场景中,已经说明知识点消化的足够好了。但是下面的彩蛋知识点,还需要一点运气才能获得~因为它并没有在包含块的MDN文档中被提及。

chrome率先实现了一个实验特性contain。它允许开发者声明当前元素和它的内容尽可能的独立于 DOM 树的其他部分。从而使得浏览器在重新计算布局、样式、绘图或它们的组合的时候,只会影响到有限的 DOM 区域,而不是整个页面。

在它的可选值中,paint的作用是使得该元素的子孙节点不会超出它的边缘。

那父元素contain: paint和子元素position: fixed结合会如何呢?

实验结果是,fixed的元素表现得像是父元素设置了transform/perspective/filter一样,说明它的包含块被contain: paint属性所影响。

MDN文档中没提到,那是Chrome意外实现了一个彩蛋吗?

The element acts as a containing block for absolutely positioned and fixed positioned descendants.

参考

  1. Layout and the containing block
  2. contain
  3. containment-paint


请遵守《互联网环境法规》文明发言,欢迎讨论问题
扫码反馈

扫一扫,反馈当前页面

咨询反馈
扫码关注
返回顶部