你不知道的CSS之包含块
什么是包含块?
包含块(containing block),顾名思义,就是一个包含其他元素的“块”。但它可不只是一个简单的容器哦!它不仅影响子元素的位置,还会影响到**宽度、长度、内外边距(padding、margin)、甚至定位(position)**等各种CSS属性的计算。
例如,像下图一样,很多时候我们看不见它的存在,但它正在幕后默默工作。它的作用,就是决定元素的尺寸和位置,特别是当我们使用百分比值时,计算依据就是包含块的尺寸。
是不是感觉它像个隐藏的大boss,一切似乎都在它的掌控之中?
简单的例子,告诉你包含块怎么“作妖”!
好,让我们从一个简单的例子开始:
1 |
|
1 |
|
根据上面的代码,你一定会说:div.item
的宽度是250px,高度是150px。嗯,没错!但是你知道吗,这个答案虽然正确,但并不完全准确!真正的计算方式是这样的:
div.item
的尺寸,实际上是通过它的包含块来计算的!
在这个例子里,div.item
的包含块是div.container
,也就是它的父元素。因为div.container
的宽度是500px,所以50%的宽度就是250px;高度300px,所以50%就是150px。
所以,记住:百分比计算的依据是包含块的尺寸,而不是父元素的尺寸!
包含块的规则:绝对定位的奇妙之处
好,现在我们进入了包含块的“黑洞”——对于绝对定位元素,包含块是怎样计算的呢?看一下这个神秘的例子:
1 |
|
1 |
|
你可能已经脑补了div.item2
的位置,但让我来帮你补充一下:div.item2
的包含块是div.container
,而不是div.item
!因为div.container
有position: relative;
的属性,它是一个定位容器。
所以当你使用position: absolute;
时,包含块的计算会参照最近的定位祖先元素,而不是简单的父元素。这就是为什么div.item2
的包含块是div.container
的原因,而不是div.item
。
一些更“迷”的例子:Transform与包含块
接下来,让我们来看看transform如何影响包含块的计算:
1 |
|
1 |
|
这里,我们为.item
添加了transform: rotate(0deg)
,看似没变化,但在实际渲染中,你会发现**div.item2
的包含块变成了div.item
**,而不再是div.container
。原因就是:transform让div.item
变成了一个块容器,因此div.item2
的包含块就“变脸”了。
惊天大揭秘!包含块的实际应用
让我们总结一下吧!你已经掌握了最重要的几点:
- 根元素(
html
)的包含块就是浏览器的视口(viewport
),大小等于屏幕可视区域。 - 对于非根元素,包含块的计算主要基于其最近的定位父元素,如果该父元素是
position: relative
、absolute
、fixed
或sticky
,那么包含块就由它决定。 - 对于
absolute
定位的元素,包含块是它最近的定位祖先元素的内边距区的边缘。 - 你还得知道:transform、will-change等属性也能改变包含块的行为。
最后再来看一些有趣的例子:
元素 | 包含块 |
---|---|
html | 初始包含块(视口) |
body | html |
div1 | body |
p1 | div1 |
p2 | div1 |
em1 | p2 |
strong1 | p2 |
如果你对div1
进行了定位,比如加上position: absolute;
,那么它的包含块就会变成初始包含块,而不再是body
了。
1 |