为什么CSS2.1定义了“可见”以外的溢出值来build立一个新的块格式化上下文?

CSS2.1规范要求除了visible其他overflowbuild立一个新的“块格式化上下文” 。 这让我觉得很奇怪,一个显而易见的目的是隐藏溢出而不影响布局的属性实际上确实影响了布局。

看起来像溢出值除了visible结合了两个完全不相关的特性:是否创build了BFC以及溢出是否隐藏。 没有BFC就不像“overflow:hidden”是完全没有意义的,因为浮动历史上可以溢出他们的父元素, 隐藏溢出而不改变布局似乎是明智的。

假设他们是已知的,这个决定背后的原因是什么? 那些从事这个规范工作的人们说明了为什么会这样做?

我代表你在邮件列表上询问了这个问题。 线程可以在这里find。 总之, 这与滚动大部分内容有关 :

基本上,因为如果规范没有这样说,那么浮动与可滚动的东西相交会要求浏览器在每次滚动时重新包装(围绕入侵浮动)可滚动元素的内容。 这在技术上是CSS 2.0所要求的,但是它从来没有实现过,而且滚动的速度也是一个巨大的问题。

-大卫

最有可能的是,它指的是一个框中的可滚动内容,可能出现在浮动的父项之外,但会与浮动相交。 我不认为这与重新包装可滚动容器内的浮动内容有关,因为这已经是自然发生的事了,再加上浮动将会剪切到容器中,并随着其内容一起滚动 。

最后这对我有意义。 事实上,我将在这里提供一个例子,希望对您和任何可能想知道的人都有意义。 考虑一个涉及两个具有相同的固定高度和overflow: visible框的场景overflow: visible (默认值),其中第一个包含一个伸展超出父级高度的浮点数:

 <div> <p>...</p> </div> <div> <p>...</p> <p>...</p> </div> 
 /* Presentational properties omitted */ div { height: 80px; } div:first-child:before { float: left; height: 100px; margin: 10px; content: 'Float'; } 

注意与第9.5节给出的一个例子的相似之处。 这里的第二个盒子只是简单地显示出满足这个答案的内容。

这是没有问题的,因为内容不会被滚动,但是当overflow被设置为除了visible之外的东西时,这使得内容不仅被框的边界所裁剪,而且被滚动。 如果第二个盒子overflow: auto ,这就是浏览器实现了原始CSS2规范的样子:

由于浮动,尝试滚动内容将导致浏览器不得不重新包装它,所以它不会被浮动(和滚动的顶部边缘部分会发生什么?)。 滚动到底部时,它可能看起来像这样:

这里的问题在于,浏览器在滚动时不得不重新打包内容。 对于能够进行基于像素的平滑滚动的浏览器 – 也就是说,所有这些浏览器 – 我都能明白为什么会是性能灾难! (用户也体验一个。)

但是,这是为了当用户可以滚动的内容,对不对? 这对overflow: auto有意义的overflow: autooverflow: scroll ,但overflow: hidden

那么,一个常见的误解是,容器overflow: hidden只是通过剪辑隐藏内容,不能滚动。 这不完全正确 :

虽然没有提供滚动用户界面,但内容仍然可以通过编程方式滚动,而许多页面只执行滚动(例如,通过在相关元素上设置scrollTop )。

-Boris

事实上,如果第二个盒子设置为overflow: hidden ,这就是它的样子overflow: hidden ,然后用下面的JavaScript滚动到底部:

 var div = document.getElementsByTagName('div')[1]; div.scrollTop = div.scrollHeight; 

同样,请注意,内容将不得不重新包装,以避免被浮动模糊。

即使这不会像滚动UI的性能那样痛苦,但我最好的猜测是,他们使除了visible以外的任何 overflow值的盒子主要为了一致性而生成新的BFC。


所以,这个变化是在CSS2.1中产生的,logging在这里 。 现在,如果将除visible以外的overflow值应用于第二个框,则浏览器所做的是将整个框放在一边,以便为float创buildpath,因为框现在创build一个新的块格式上下文,用于封装其内容,而不是在浮子周围stream动。 这个特定行为在下面的段落中被指定:

表格,块级别replace元素或正常stream程中用于build立新块格式上下文的元素(例如“可见”以外的“溢出”元素)的边框不得与与元素本身在同一个块格式上下文中浮动。 如果有必要的话,实施应该通过将其放置在任何前面的浮体之下来清除所述元素,但是如果有足够的空间,可以将其放置在这样的浮体附近。 他们甚至可能使该元素的边框比第10.3.3节定义的窄。 CSS2并没有定义何时UA可以将所述元素放置在浮子的旁边,或者所述元素可能变得更窄。

下面是overflow: auto样子overflow: auto例如:

请注意,没有清除; 如果第二个箱子有clear: leftclear: both无论是否build立了自己的BFC,它都会被推倒,而不是在旁边。

如果将overflow: auto应用于第一个框,则由于其固定的高度,浮动被剪切到其包含的框中,因为它的固定高度在上面给出的示例代码中设置为80px

如果您将第一个框恢复为height: auto (默认值),则通过覆盖或从上面删除height: 80px声明,然后延伸到float的高度:

这恰好在CSS2.1中也是新的 ,因为一个带有height: auto的元素会生成一个新的块格式化上下文(即块格式化上下文根 ),这个元素将垂直拉伸到其浮点的高度,而不仅仅是包含不同于常规盒子的stream内容。 这里和这里logging的变化。 此处logging了导致收缩箱子的副作用的变化,使其不与浮子相交。

在这两种情况下,不pipe你对第二个盒子做什么,它都不会受到浮子的影响,因为它受到了容器边界的限制。

我知道这将是一个推测性的答案,然而在阅读规范几次这里是我的观点:

第9.4.1节讨论的是任何不完全包含或不填充容纳空间的块元素。 例如,当你浮动一个元素时,它不再填充父元素的100%,就像stream内元素一样。 内联块,表格单元格和表格标题也是可以影响高度和宽度的元素,但本质上并不是100%(是> table> tr> td是填充其父元素的100%,但它是devise的以允许多个td,所以td不会计数,因为它会自动缩小以容纳额外的td),这也适用于除了可见之外的任何溢出,因为它打破了块元素的包含。

因此,如果我正确读取它的话,它的工作方式是9.4.1节所指的块元素,这些块元素按照9.2.1节的规定破坏块元素的默认包含规则