为什么CSS2.1定义溢出值而不是"可见"来建立新的块格式化上下文?

Rom*_*kov 58 css overflow

CSS2.1规范要求overflow除了visible建立新的"块格式化上下文"之外.这让我觉得很奇怪,一个明显的目的是隐藏溢出而不影响布局的属性实际上确实会以一种主要方式影响布局.

看起来像溢出值除了visible组合两个完全不相关的特征之外:是否创建了BFC以及是否隐藏了溢出.它不像"溢出:隐藏"在没有BFC的情况下完全没有意义,因为浮动历史上可以溢出它们的父元素,隐藏溢出而不改变布局似乎是明智的.

这个决定背后的原因是什么,假设它们已知?那些参与规范工作的人是否描述了为什么决定这种情况?

Bol*_*ock 66

我代表你在邮件列表上询问了这件事; 线程可以在这里找到.总之,这与滚动内容大部分有关:

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

-大卫

最有可能的是,它指的是一个框中的可滚动内容,它可能出现在float的父级之外,但会与float相交.我不认为这与在可滚动容器内的浮动内容重新包装内容有关,因为这已经自然发生,加上浮动将剪切到容器中并且无论如何都会滚动其余内容.

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

<div>
    <p>...</p>
</div>
<div>
    <p>...</p>
    <p>...</p>
</div>
Run Code Online (Sandbox Code Playgroud)
/* Presentational properties omitted */
div {
    height: 80px;
}

div:first-child:before {
    float: left;
    height: 100px;
    margin: 10px;
    content: 'Float';
}
Run Code Online (Sandbox Code Playgroud)

请注意与9.5节中给出的示例之一的相似之处.为了这个答案的目的,这里的第二个框被简单地显示为具有溢出的内容.

这很好,因为内容永远不会滚动,但是当overflow设置为不同visible的内容时,这会导致内容不仅被框的边界剪切,而且还变得可滚动.如果第二个框有overflow: auto,这就是浏览器实现原始CSS2规范时的样子:

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

这里的问题是浏览器必须在滚动期间每次重新绘制内容时重新包装内容.对于能够进行基于像素的平滑滚动的浏览器 - 也就是说,所有这些浏览器 - 我可以看到它为什么会出现性能灾难!(还有一个用户体验一个.)

但这是因为用户可以滚动内容,对吗?这对于overflow: auto和有意义overflow: scroll,但是呢overflow: hidden

嗯,一个常见的误解是容器overflow: hidden只是通过剪切隐藏内容而无法滚动.这不完全正确:

虽然没有提供滚动UI,但是内容仍然可以以编程方式滚动,并且多个页面仅执行这样的滚动(例如,通过设置scrollTop相关元素).

-Boris

实际上,如果将第二个框设置为overflow: hidden然后使用以下JavaScript滚动到底部,则会出现这种情况:

var div = document.getElementsByTagName('div')[1];
div.scrollTop = div.scrollHeight;
Run Code Online (Sandbox Code Playgroud)

再次注意,必须重新包装内容以避免被浮动遮挡.

即使这对于性能不如滚动UI可用的那么痛苦,我最好的猜测是他们制作了除了生成新BFC 之外的任何 overflow其他值的盒子,visible主要是为了保持一致性.


因此,这一变化是在CSS2.1中引起的,在此处记录.现在,如果你只将一个overflow值应用于visible第二个框,那么浏览器所做的就是将整个框一边以便浮动,因为该框现在创建一个新的块格式化上下文,它包含其内容,而不是流动漂浮.以下段落中指定了此特定行为:

表的边框,块级替换元素或正常流中建立新块格式化上下文的元素(例如"溢出"除"可见"之外的元素)不得与边框重叠.与元素本身相同的块格式化上下文中的任何浮点数.如果需要,实现应该通过将所述元素放置在任何前面的浮动下面来清除所述元素,但是如果有足够的空间,可以将它放置在这些浮动的附近.它们甚至可能使所述元素的边框比第10.3.3节所定义的更窄.CSS2没有定义何时UA可以将所述元素放在浮点旁边或者所述元素可能变得更窄.

以下是它的样子overflow: auto:

请注意,没有间隙; 如果第二个盒子有clear: left或者clear: both它会被推,而不是侧面,无论它是否建立了自己的BFC.

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

如果将第一个框恢复为height: auto(默认值),或者通过覆盖或height: 80px从上面删除声明,它会延伸到浮动的高度:

在CSS2.1中也是新的,因为带有height: auto该元素的元素生成一个新的块格式化上下文(即块格式化上下文根)将垂直拉伸到其浮点的高度,而不仅仅是足以包含它 - 流量内容与常规盒子不同.这里这里记录这些变化.导致萎缩的框,以便它不相交浮动的副作用的变化记录在这里.

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