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

时间:2012-03-30 13:00:38

标签: overflow css

CSS2.1规范mandates that overflow other than visible establish a new "block formatting context"。这让我觉得很奇怪,一个明显的目的是隐藏溢出而不影响布局的属性实际上确实会影响布局。

似乎除visible之外的溢出值组合了两个完全不相关的特征:是否创建了BFC以及是否隐藏了溢出。它不像“溢出:隐藏”在没有BFC的情况下完全没有意义,因为浮动历史上可以溢出它们的父元素,hiding the overflow without changing the layout似乎是明智的。

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

2 个答案:

答案 0 :(得分:66)

我代表你在邮件列表上询问了这个问题;可以找到该帖子here。总之,this has to do with scrolling content for the most part

  

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

     

-David

最有可能的是,它指的是一个框中的可滚动内容,它可能出现在浮动的父级之外,但会与浮动相交。我不认为这与在可滚动容器内的浮动内容重新包装内容有关,因为这已经自然发生,加上the float would clip into the container and scroll along with the rest of its content anyway

最后这对我有意义。事实上,我将在这里提供一个例子,所以希望你和其他可能想知道的人都有意义。考虑一个涉及两个具有相同固定高度和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';
}

请注意与section 9.5中给出的一个示例的相似性。为了这个答案的目的,这里的第二个框只是显示有溢出的内容。

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

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

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

但是用户可以滚动内容,对吧?这对overflow: autooverflow: scroll有意义,但overflow: hidden怎么办?

嗯,一个常见的误解是,overflow: hidden的容器只是通过剪切隐藏内容而无法滚动。 This is not completely true

  

虽然未提供滚动UI,但内容仍可以编程方式滚动,并且许多页面仅执行此类滚动(例如,通过在相关元素上设置scrollTop)。

     

-Boris

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

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

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

即使这不会像滚动用户界面那样令人痛苦,但我最好的猜测是,他们使用除{{之外的任何 overflow值制作了一些框。 1}}生成一个新的BFC主要是为了保持一致。


因此,这一变化是在CSS2.1中引起的,记录为here。现在,如果您将visible以外的overflow值仅应用于第二个框,那么浏览器所做的就是将整个框推到一边,为浮动让路,因为框现在创建一个新的块格式化上下文,它包含其内容,而不是在浮动周围流动。此特定行为在以下paragraph中指定:

  

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

以下是visible的内容,例如:

请注意,没有许可;如果第二个框有overflow: autoclear: left,则无论是否建立了自己的BFC,它都会被推送,而不是推向一边。

如果您将clear: both应用于第一个框,则浮动内容将被剪切到其包含框中,其余内容由于其固定高度而导致,在示例代码中将其设置为overflow: auto如上所述:

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

这恰好是new in CSS2.1 as well,因为生成新的块格式化上下文(即块格式化上下文根)的height: 80px元素将垂直延伸到它的浮子的高度,不仅仅足以容纳其流入的内容,不像普通的盒子。记录的更改为hereherehere记录了导致收缩盒子以使其不与浮子相交的副作用的变化{/ 3}}。

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

答案 1 :(得分:4)

我知道这将是一个推测性的答案,但是在阅读规范之后,我对此有几次观点:

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

因此,如果我正确地阅读它的工作方式是9.4.1部分指的是破坏块元素的默认包含规则的块元素,如9.2.1节所述