CSS3: 剪切父元素和双列子元素:混合平衡和非平衡 column-fill

4
在我的文档中有一个固定高度的父级div和一个两列子级div
<div id="parent">
    <div id="child">Text</div>
</div>

使用纯CSS3,我正在尝试让子元素的两列布局与父元素的溢出裁剪协同工作,具体如下:
  1. 当子元素包含少量文本时,它不应该平衡两列,即它应该像 column-fill: auto 一样行事。

    non-balanced column fill with little text

  2. 如果第一列超出了父容器的底部,子元素的文本应该自动换行到第二列。

    enter image description here

  3. 然而,当子元素的文本量超过父容器的容量时,子元素的两列应该保持平衡,并且父容器应该裁剪子元素,同时在右侧出现垂直滚动条。

    enter image description here


3
请提供一个示例代码片段,或至少提供您的代码片段。 - Mathew Thompson
好的,基本上就像我说的那样:父级 div 和子级 div。现在还没有 CSS(这就是我要求的)。 - wnrph
1
据我所知,如果没有一些JS的参与,这是不可能实现的...但期待一些纯CSS3的解决方案...另外,奇怪的设计,强制用户向上滚动以继续阅读第二列...在我看来,栏目最好像报纸一样整体呈现。 - Roko C. Buljan
1
同意。但这正是客户喜欢看到的。 - wnrph
如果你雇人为你建房子,但告诉承包商你不想要任何窗户或门,你不会期望他告诉你这不是一个好主意吗...即使那是你真的真的想要的? - Ryan Wheale
@Ryan 如果我是一名自由职业的架构师,承包商有几位高级架构师决定这正是他们想要的,那就不是我的问题了。 - wnrph
1个回答

3
简而言之,在编写本文时,您无法使用纯CSS3实现您想要的内容。您需要的目标API是CSS3多列。如果您查看规范中的示例,您将会发现它并没有考虑在同一元素上同时混合平衡和非平衡(顺序)列填充的用例。
该规范旨在在不同时间实现不同技术,因此类似(但最终略有不同)于您请求的功能。然而,我们可以通过一点javascript的帮助来实现您的目标功能!以下是说明和代码已在Chrome 38和FF 33 IE 11上测试
如果您想学习一些新东西,请查看mutationobserver,它可能会缓解您在评论中提到的问题(不知情的开发人员在运行时更改内容)。它允许我们跟踪dom更改并适当地设置类。我的第一次尝试成功了,但不是跨浏览器的,请参见回滚之前的编辑版本。
我将把您的三个要求称为状态。
概述
  • 状态1和状态2共享相同的css (column-fill:auto)。
  • 由于多列规范,状态3需要不同的css规则(column-fill:balance)。
  • 仅在状态1和状态2无法容纳所有文本(即溢出)时,才需要状态3的规则以实现所需功能。
  • 借助javascript的帮助,当状态1和2中存在溢出时,我们可以应用状态3的类更改。
  • 反之,如果删除内容,则在更改时可以重新应用状态1和2的类。
  • css属性column-count是跨越给定父元素的列数。在您的情况下,我们希望有2个。

实现状态1和状态2

每当您设置列元素的高度时,浏览器会在没有足够空间时向外呈现更多的列。列宽度为目标跨度的宽度。因此,设置高度是为了使列按顺序填充(如您请求的"像column-fill:auto")。请参见下面的代码片段,"origState"的css规则适用于状态1和状态2。

实现第三种状态

然而,这种状态会给我们带来一个问题。当设置列的高度时,溢出会产生更多与原始列宽度相同的列。现在你想让它像 column-fill:balance 一样行为,具有无限高度,可以滚动。在使用顺序填充(即 column-fill:auto)时,这在 css3 多列规范中是不可实现的。然而,在列中未设置高度且在父元素中设置了高度(使用适当的滚动 css 值),我们可以实现你想要的效果。请参见下面的代码片段,"overFlowState" 的 css 规则应用于第三种状态,注意已删除高度

完整解决方案

现在我们必须将两个目标功能请求结合起来。你必须确定何时将第二个类应用于子容器,这可以通过检查状态 1 和 2 上的溢出来完成。可以在元素添加到 dom/domready 后进行此检查。(本来打算自己编写,但从 this post 借用了检查溢出的 javascript 函数)。请参见下面的 javascript 代码片段。

function isOverflowed(element){
    return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}
var elements = document.getElementsByClassName("origState");
for(var i = 0; i < elements.length; i++){
    var element = elements[i];
    if(isOverflowed(element)){
       element.className = "overFlowState";
       i--;
    }
}
.parent{
    overflow-x:hidden;
    overflow-y:auto;
    width:100%;
    height:7em;
}
.origState{
    -webkit-column-count:2;
    -moz-column-count:2;
    column-count:2;
    -moz-column-fill:auto;
    height:inherit;
}
.overFlowState{
    -webkit-column-count:2;
    -moz-column-count:2;
    column-count:2;
}
<div class="parent">
    <div class="origState">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
    </div>
</div>
<div class="parent">
    <div class="origState">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat 
        </div>
</div>
<div class="parent">
    <div class="origState">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius.
    
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius.
        </div>
</div>

结论

问题在于当设置了高度时,列内容溢出应该生成更多的列。我们可以通过在css中删除列高度来获得父级预期的滚动区域。我们可以借助JavaScript交换类名将两者结合起来。


2
为什么这个还没有+1?@artistoex,你也应该点赞,也许它不是你的最终解决方案,但比你之前的要好得多,而且似乎付出了很多努力。 - Andrea Ligios
@AndreaLigios,完全同意.. 给你点赞。 - vals
1
@Art +1 你在这个答案中付出了令人印象深刻的努力。我想这是目前最好的答案。我的主要关注点是可持续性。这将成为一个相当大的代码库的一部分。几年后,不是所有参与者都会意识到不能自由修改某些元素。我想知道溢出检测部分是否仍然有效。如果不是纯CSS3,我至少正在寻找一种可以立即应用且永远不需要再次关注的解决方案。这就是为什么我犹豫授予赏金的原因。 - wnrph
@artistoex 这很容易理解。我仔细考虑了一下,研究了css3的css-regionsdynamic-css(更多关于不同屏幕分辨率的css),伪类伪元素-- 我在所有这些方面都遇到了问题,需要一些javascript的帮助。我认为css3多列是最接近纯css解决方案的方式,因为目前规范如此。我有一个想法,可以满足您对修改的担忧--我会在本周末/有更多时间时尝试并修改我的建议解决方案(同时澄清一些措辞)。 - Arthur Weborg
哎,不幸的是我的尝试有些错误,无法跨浏览器工作...我试图利用DOM4 mutationobserver api来钩取内容更改...回滚了答案,但如果你想进一步探索它,可以查看答案的修订历史。 - Arthur Weborg
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接