原文: When And How To Use CSS Multi-Column Layout
做者:Rachel Andrew
译者:博轩
当咱们把注意力都放在 CSS Grid
布局和 CSS Flexbox
布局的时候,常常忽略了另外一种布局方法。在本文中,我将介绍多列布局 - 一般称为 multicol
或者 “CSS Columns” 。经过这篇文章,你了解到使用 columns
的最佳实践,以及一些使用 columns
的注意事项。css
multicol
的基本思想是,你能够把一大块内容带到多个列中,就像报纸同样。您可使用两个属性中的其中一个来完成此操做。您可使用 cloumn-count
属性来指定内容的列数。还可使用 column-width
属性来指定理想的列宽,让浏览器来决定合适的列数。git
不论你的内容包含什么样的元素,当你将它转换为多列布局时,一切都将保持正常的内容流,可是将以列的形式展示。这使得 multicol
布局与现在在浏览器中常见的其余布局会有所不一样。例如 Flexbox
和 Grid
,获取容器元素中子元素,让这些子元素参与到 flex
和 grid
的布局中来。使用 multicol
,在每一列的内部,您还能够得到正常的内容流。github
在下面的例子中,咱们正在使用 column-width
,最小列宽为 14em
。Multicol
会尽量多的分配宽度为 14em
的列,而后,让每一列分享剩余的空间。每一列的宽度至少 14em
,除非,容器的宽度小于 14em
,那么将只展现一列。multicol
也是 CSS
中首次出现的一种行为,能够建立出列,同时也默认符合响应式的规则。您没必要增长 CSS 查询条件 (Media Queries
) ,修改每个断点的列数,而是制定一个最佳的宽度,让浏览器自身来进行处理。web
示例连接设计模式
// 核心代码摘录
.container {
max-width: 800px;
margin: 0 auto;
column-width: 14em;
}复制代码
当你使用列属性(columns
)来建立布局的时候,cloumns box
中的内容将没法定位。您没法使用 JavaScript
来进行定位,您也没法为单个列来指定惟一的样式,好比背景颜色,外边距,内边距等等。全部 column boxes
将保持相同的大小。你惟一能够作的事情,就是使用 column-rule
属性来添加列之间的规则,该属性的做用相似于 border
。您还可使用 column-gap
属性控制列之间的间隙,该属性的默认值为 1em
,可是您还能够将其改成任何有效的长度单位。浏览器
示例连接安全
// 核心代码
.container {
max-width: 800px;
margin: 0 auto;
column-width: 14em;
column-gap: 2em;
column-rule: 1px solid #ccc;
}复制代码
这是 multicol
的基本功能。您能够将一大块内容拆分为列。内容将依次填充到每一列,并在内联的方向建立这些列。您能够控制列之间的间隙以及规则,使用与 border
相同的取值便可。到目前为止,上述全部内容在浏览器中获得了很好的支持,而且已经存在了很长时间,使得这个规范在向后兼容性方面很是安全。ide
您可能须要考虑使用列的其余一些事项,以及在Web上使用列时须要注意的一些潜在问题。布局
有时候,您可能但愿将某些内容分解为列的同时,使用一个元素跨越这些列。将 columns-span
属性用于 multicol
能够实现这一点。flex
下面的示例中,我使用一个 <blockquote>
元素来跨越列。请注意,在执行此操做时,内容会被分为两个区域,分别位于设置了 column-span
元素的上下两个部分。内容不会跳过设置了 column-span
的元素。
column-span
属性目前已在 Firefox 中实现,而且向后兼容。
// 核心代码
blockquote {
font: 2em 'Berkshire Swash', cursive;
margin: 0;
column-span: all;
text-align: center;
}
.container {
max-width: 800px;
margin: 0 auto;
column-width: 14em;
column-gap: 2em;
column-rule: 1px solid #ccc;
}复制代码
要知道,目前的规范,column-span
的取值只有 all
或者 none
。若是你想实现报纸中的样式,可使用多列布局结合其余布局来实现。在下面的示例中,咱们实现了一个带有两个列轨道的网格容器(Grid)。左边轨道的宽度是 2fr
,右边轨道的宽度是 1fr
。咱们将左边的轨道变成了一个具备两栏的 multicol
容器。它一样包含了一个跨栏元素。
在右边,咱们将内容放入第二个 Grid
列轨道中。经过尝试各类布局方法,咱们能够确切地找出适合手头工做的布局方法 - 不要惧怕混合搭配!
// 核心代码
.container {
max-width: 800px;
margin: 0 auto;
display: grid;
grid-gap: 1em;
grid-template-columns: 2fr 1fr;
align-items: start;
}
.container article {
column-count: 2;
column-gap: 2em;
column-rule: 1px solid #ccc;
}
.container aside {
border-left: 1px solid #ccc;
padding: 0 1em;
}复制代码
若是您的内容中包含标题,您可能但愿避免标题出如今列的末端,而内容却出如今了下一列中。再好比,您的内容中有一些带有文字说明的图片,那么理想的状况下,图片和他的文字说明,将保持一个总体展现,而不会被跨列分割。
当您将内容拆分为列时,这种行为被称为CSS片断模块(Fragmentation) 。将内容分割成两页进行展现,就好像打印机选择两栏的打印模式同样。所以,相比较Web上的其余布局方法,multicol
是最接近Paged Media
的布局方法。所以,咱们可使用属于CSS2.1 的属性 page-break
来实现这一点。
page-break-before
page-break-after
page-break-inside
最近,CSS片断模块规范定义了如何为各类片断模块上下文设计的碎片化的属性,规范包括 Paged Media
,multicol
和处于停滞状态的区域样式(Region Styling); 区域也会支持展现被分解(碎片化)连续的内容。经过使用这些通用属性,它们能够应用于任何将来的CSS片断模块上下文,就像 Flexbox
的对齐属性被移动到 Box Alignment
规范中同样,以便它们能够在 Grid
和 Block
布局中使用。
break-before
break-after
break-inside
下面的示例中,我在 <figure>
元素中使用 break-inside avoid
属性,防止图像的标题和图像分离。支持该属性的浏览器中,咱们应该能够看到联合在一块儿的效果,即便这会致使列中的内容看起来不平衡。
// 核心代码
figure {
margin: 0;
break-inside: avoid;
}
.container {
max-width: 800px;
margin: 0 auto;
column-width: 14em;
}复制代码
不幸的是,在 multicol
中对这些属性的支持很是不完整。即便在支持的状况下,它们也应该被视为一个建议,由于在实际使用的时候,会提出不少要求来控制内容是否应该被分离,可是实际上浏览器并不会真正让这些内容分离。在上面的示例中,咱们定义了展现的优先级,可是当您在使用的时候仍是要谨慎一些,仅在最须要的地方使用。
咱们在浏览网页时,并无看到 multicol
被普遍的使用,其缘由是读者的阅读习惯,一般是自顶向下滚动阅读的。对于使用英语,或其余垂直写做的人来讲,横向的布局并非很好的阅读体验。
若是你固定容器的高度,例如使用 viewport
单位 vh
,当内容过多时,它会在内联方向溢出,同时,你会获得一个横向的滚动条。
这些状况都不是很理想。因此,在使用多列布局的时候,咱们须要仔细的考虑每一栏的内容量。
在 Level 2
的规范当中,咱们考虑如何使用一种方法,列的内容不会溢出,生成横向的滚动条,而是在块的方向上面生成新的列。这意味着您能够拥有一个具备高度的 multicol
容器,而且一旦内容超出了该容器的宽度,就会在下面建立一组新的列。这看起来有点像咱们上面的跨越示例,可是,不是让设置了column-span
的元素致使新的列框开始,而是由块大小限制的容器宽度,从而解决溢出的问题。
此功能将使 multicol
对Web更有用。虽然咱们如今还有一段距离,但您能够关注CSS工做组回购中的问题。若是您有此功能的其余用例,请发布它们,它在设计新功能时很是有用。
使用当前规范,不建议将全部内容拆分为列而不考虑滚动问题。可是,在某些状况下,multicol
对于 web
是理想的。在查看设计模式时,有足够的示例k可供你参考。
multicol
能够在任何须要占用较少空间的项目列表的地方使用。例如,复选框的简单列表或名称列表。一般在这些状况下,访问者不会读取一列而后返回到下一列的顶部,而是扫描内容以选中要单击的复选框或要选择的项目。即便您确实建立了滚动体验,这个问题也依然存在。
您能够在 DonarMuseum网站 上看到 Sander de Jong以这种方式使用的 multicol
示例。
有时,咱们设计一个网站,咱们知道某些内容区域相对较小,而且适合大多数屏幕展现,且不须要滚动。我在 Notist演示页面使用了 multicol
,用于介绍演讲。
Andy Clarke 为 Equfund网站 设计了一个可爱的例子。
为了不很是小的屏幕致使页面出现滚动,就像宽度同样,您可使用媒体查询来检查高度。对于超出最小高度的内容,您能够在断点处设置 min-height
,来避免用户使用较小设备时所带来的较差体验。
多列布局工做得很漂亮的另外一个地方是,若是要建立瀑布流的内容显示。Multicol
是目前惟一一种,能够建立不定高度的布局方法。Grid
布局要么会留下间隙,要么拉伸项目以造成严格的二维网格。
Veerle Pieters 有一个很好的例子,就是在她的灵感页面上以这种方式使用multicol
。
这些 column-
属性还能够用做 Grid
和 Flex
布局的备选方案。若是在容器上指定其中一个属性,则使用 display: flex
或 display: grid
将删除任何列行为,将该容器转换为 Flex
或 Grid
布局。例如,若是你有一个使用 Grid
布局的卡片布局,若是它在列中而不是在页面上运行,那么布局就是可读的,你可使用 multicol
做为简单的后备。不支持 Grid
的浏览器将得到 multicol
显示,支持 Grid
的浏览器将得到 Grid Layout
。
我常常回答 Grid
和 Flexbox
的问题,答案是不使用 Grid
或 Flexbox
,而是试试 Multicol
。您可能不会在每一个站点上使用它,可是当您遇到本文中提到的场景时,它可能很是有用。在MDN上有关于 multicol和CSS片断模块的有用资源。
若是您在项目中有 multicol
的其余使用场景,也欢迎留言分享!
本文已经联系原文做者,并受权翻译,转载请保留原文连接