html - 为什么在浏览器中,overflow:hidden会中断多列渲染,而在Chrome中却不能?

标签 html css google-chrome firefox css-multicolumn-layout

最近,我偶然发现Firefox中的一个奇怪行为,其中包含columns:2 div中的列表。

如果列表设置了overflow:hidden,则Firefox将不再在2列中呈现。可以在Chrome中按预期在2列中进行渲染(有无溢出)。

这是一个最小的示例:



$('button').on('click', (e) => {
  $('ul').toggleClass('overflow')
})

div {
  columns:2;
}

ul.overflow {
  overflow: hidden;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>toggle overflow</button>
<div>
    <ul>
        <li>Lorem ipsum dolor.</li>
        <li>Consequuntur, ab nostrum.</li>
        <li>Quibusdam, iure, fuga.</li>
        <li>Suscipit quisquam, vel.</li>
        <li>Assumenda architecto, adipisci!</li>
        <li>Molestias, nostrum ratione.</li>
        <li>Quaerat, eveniet, in.</li>
        <li>Illum, debitis, dicta.</li>
        <li>Tempore, placeat, ea.</li>
        <li>Amet dignissimos, maiores.</li>
        <li>Odio, eos, ullam.</li>
        <li>Modi libero, quis!</li>
        <li>Aliquid, commodi, voluptates.</li>
        <li>Aperiam, magni, vel.</li>
        <li>Vitae, minima dolorum!</li>
        <li>Quidem, corporis, dolorum.</li>
        <li>Autem, minima, sit.</li>
        <li>Adipisci, odio, numquam.</li>
        <li>At, dicta, hic!</li>
        <li>Odit, blanditiis voluptate.</li>
    </ul>
</div>





在CodePen上:
https://codepen.io/BugHunter2k/pen/rNaVpGG

什么渲染是正确的?
我可以添加一些内容吗,即使使用overflow:hidden,Firefox也会显示2列

最佳答案

尽管Thierry的答案包括解决一个问题的解决方案,但它也可以解决您面临的实际问题(我相信,这是无意中的),并且错误地归咎于错误的浏览器。让我们分解一下:

首先,这实际上在Firefox中正常工作,在Chrome中不正确。

由于columns: 2,您有一个div充当multi-column container,它是以下各项的简写:

div {
    column-count: 2;
    column-width: auto;
}


这个多列容器建立了一个新的block formatting context,因此后代元素上的所有属性都将相对于div而非本例中的页面应用。

要记住的一件事是,多列布局有点灵活(我也不是说关于flexbox布局)...它们会尝试遵守您提供的值,但是如果它们适合较少的列,或者如果他们必须占用更多的列以适合您的标记,则很可能会这样做。您稍后会在我的答案中看到一个示例。

在div中,您有一个无序列表,该列表通常在垂直列表中显示其子级,但是由于前面的columns: 2,您的<ul>会自动拆分为尽可能适合的两列。因为在任何地方都没有声明heightwidth属性(通常或作为column-属性),所以它只将内容分割为50-50。您在列表的两半之间看到的未对齐是因为<ul>默认情况下具有margin-top属性,该属性会将列表项的前半部分向下推16px(通常是<ul> s上的边距大小)。

columns: 2中应用ul {}而不是div {}可以解决您的问题的原因是因为您现在将<ul>本身分为两列,而不是试图将普通的<ul>挤进一个多列容器中但是它可以容纳;浏览器知道以这种方式将相同的格式应用于每列的开头。

现在,默认情况下,<div>的宽度与容器的宽度相同(由于其默认的display:block;属性),与容器的内容一样高。如果要向<ul>添加更多项目,则两组列表项的高度会增加(如果为div设置了背景颜色,则可以更轻松地看到)。

提到我提到的灵活性,如果您将div的高度限制为150px,您会发现默认情况下列数增加并且div溢出:



div {
    columns:2;
    column-rule: thin solid red; /* this value added just to illustrate the split between columns */
    height: 150px;
    background: grey; /* this value added for ease of visual comprehension */
}

ul.overflow {
    overflow: hidden;
}

<div>
    <ul>
        <li>Lorem ipsum dolor.</li>
        <li>Consequuntur, ab nostrum.</li>
        <li>Quibusdam, iure, fuga.</li>
        <li>Suscipit quisquam, vel.</li>
        <li>Assumenda architecto, adipisci!</li>
        <li>Molestias, nostrum ratione.</li>
        <li>Quaerat, eveniet, in.</li>
        <li>Illum, debitis, dicta.</li>
        <li>Tempore, placeat, ea.</li>
        <li>Amet dignissimos, maiores.</li>
        <li>Odio, eos, ullam.</li>
        <li>Modi libero, quis!</li>
        <li>Aliquid, commodi, voluptates.</li>
        <li>Aperiam, magni, vel.</li>
        <li>Vitae, minima dolorum!</li>
        <li>Quidem, corporis, dolorum.</li>
        <li>Autem, minima, sit.</li>
        <li>Adipisci, odio, numquam.</li>
        <li>At, dicta, hic!</li>
        <li>Odit, blanditiis voluptate.</li>
    </ul>
</div>





如您所见,div与容器一样宽(无论您的容器有多大),并且列被分成三部分,因为这需要适合您拥有的列表项的数量。它通过在必要时溢出children元素来尝试使列保持相等的高度。切换按钮时看到的行为的秘密就是overflow: hidden;的作用。

overflow: hidden;应用于元素时,它还会建立新的块格式上下文。创建一个新的块格式上下文基本上说“在这里从头开始重置我的布局计算;不要考虑包含块正在做什么”。在您的情况下,这是说“忽略先前的块格式上下文中的CSS列布局,而通常像<ul>那样显示”。 Chrome不会这么做,但应该这么做。可能是实施错误/不完整的情况,也可能是Chrome开发人员根据他们大多数人的意愿做出决定的情况。这两种情况在该供应商中很常见。

其次,蒂埃里(Thierry)建议修正<ul>的两个部分的垂直对齐不均匀的建议是将column属性应用于<ul>。也可以通过删除margin-top属性/将其设置为0来实现该特定目标,但是解决该目标的这种方法还可以做到以下几点:


将适当的多列布局设置应用于<ul>(正如我之前提到的,现在浏览器知道在多列布局的上下文中处理列表和列表项,而不仅仅是尝试挤压列表以多列容器)。
columns本身上设置<ul>属性意味着,当由于overflow: hidden;而创建新的块格式设置上下文时,对于<ul>忽略父级<div>的内容及其块格式,不会发生任何变化。上下文。换句话说,在overflow: hidden;创建的新块格式上下文中应用了多列布局。


如果只想将无序列表分成多列,则最终将获得所需的新行为。如果要为多列布局考虑多种类型的元素(或只是多个元素),则必须将其保留在父<div>上。

关于html - 为什么在浏览器中,overflow:hidden会中断多列渲染,而在Chrome中却不能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59198370/

相关文章:

html - 容器内的一组左浮动的固定宽度 div - 奇怪的行为(不规则地中断到下一行?)

asp.net - 我怎样才能为单个 HTML 页面添加一点点活力,同时具有最小的依赖性和最大的可移植性?

javascript - Angular 4 - 如果 ngModel 不为空则添加类

javascript - 如何在单击的元素正下方显示详细信息 div/弹出框

html - 如何卸载 Service Worker?

javascript - 使用 OpenLayer3 显示标记、弹出窗口

css - 元素的 Z-index 不会在 Chrome 中显示

html - CSS !important 声明在 Outlook 2007 中不起作用

google-chrome - 如何推广从自己的网站安装 Chrome 扩展程序?

javascript - 如何在 Chrome 扩展程序的 onHeadersReceived 事件中访问请求 header