最近,我偶然发现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>
会自动拆分为尽可能适合的两列。因为在任何地方都没有声明height
或width
属性(通常或作为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/