响应式友好的 CSS 列指南

Avatar of Katy DeCorah
Katy DeCorah

DigitalOcean 提供适用于您旅程每个阶段的云产品。立即开始使用 $200 免费信用额度!

使用 CSS 列,您可以创建受打印启发的布局,该布局只需添加很少的标记即可适应固定画布之外。支持的浏览器将进行计算以将内容包装并平衡到整齐的列中。如果您已经在使用流体布局,则列会自动重新排列。使用正确的属性组合,CSS 列可以成为一种有趣的布局选项,它既响应式友好,又可以优雅地降级。

在哪里声明列

您可以在任何块级元素上声明列。列可以应用于单个元素,也可以通过定位其父元素来应用于多个元素。

在下图中,左侧描绘了将 CSS 列规则应用于第二个段落以将该内容转换为列。右侧描绘了将规则应用于容器元素,例如 <div></div><article></article> 以将元素转换为多列布局。

single and multi element columns

如何声明列

有三种不同的方法来声明列

  1. 声明 column-count
  2. 声明 column-width
  3. 同时声明两者(推荐)。

让我们探索声明列的不同方法。

1. 声明 column-count

使用 column-count 声明列数。

article {
  -webkit-column-count: 2;
     -moz-column-count: 2;
          column-count: 2;
}

实时演示

查看 Pen [2] CSS 列,count-count 由 Katy DeCorah (@katydecorah) 在 CodePen 上。

即使浏览器宽度发生变化,列数也会保持一致,如下面的 gif 所示。

column count at narrow width

2. 声明 column-width

使用 column-width 声明列的宽度。

指定的值不是绝对值,而是最小宽度。给定 column-width,浏览器将决定可以在空间中容纳多少列至少具有该宽度。浏览器还会在此计算中考虑间隙或列之间的间距(稍后将详细介绍)。然后,浏览器将扩展列以均匀分布以填充分配容器的宽度。

例如,如果您检查以下实时演示中的段落,您会发现该列的宽度实际上大于 150px,而 150px 是 column-width 的设置值。

article {
  -webkit-column-width: 150px;
     -moz-column-width: 150px;
          column-width: 150px;
}

实时演示

查看 Pen [3] CSS 列 由 Katy DeCorah (@katydecorah) 在 CodePen 上。

一旦浏览器无法容纳至少两列与 column-width 一样宽,则不会出现任何列,并且布局将恢复为单列布局。

下面的 gif 演示了当浏览器宽度变窄时列如何释放。与 column-count 不同,此属性本质上是响应式的。

column width as the browser narrows

3. 同时声明两者(推荐)

column-countcolumn-width 结合使用以更好地控制 CSS 列。您可以声明每个属性,也可以使用简写 columns

当声明了这两个属性时,column-count 是列的最大数量,而 column-width 是这些列的最小宽度。

article {
  -webkit-columns: 2 200px;
     -moz-columns: 2 200px;
          columns: 2 200px;
}

/* or */

article {
  -webkit-column-count: 2;
     -moz-column-count: 2;
          column-count: 2;
  -webkit-column-width: 200px;
     -moz-column-width: 200px;
          column-width: 200px;
}

实时演示

查看 Pen [4] CSS 列,columns 由 Katy DeCorah (@katydecorah) 在 CodePen 上。

下面的 gif 演示了将 column-countcolumn-width 结合使用时如何随着浏览器宽度变窄而响应。

both properties as the browser narrows

自定义列

有几个属性可以进一步自定义 CSS 列。

column-gap

要调整间隙或列之间的间距,请声明 column-gap

对于大多数浏览器,column-gap 的默认值为 1em。只要它大于或等于 0,您就可以声明一个新值。

article {
  -webkit-columns: 2 200px;
     -moz-columns: 2 200px;
          columns: 2 200px;
  -webkit-column-gap: 4em;
     -moz-column-gap: 4em;
          column-gap: 4em;
}

实时演示

查看 Pen [5] CSS 列,column-gap 由 Katy DeCorah (@katydecorah) 在 CodePen 上。

尽管间隙较大,但浏览器仍会进行必要的计算以均匀地间隔和平衡列。

下面的 gif 演示了当浏览器宽度变窄时浏览器如何释放列并删除间隙。

column-gap drops when the browser width narrows

column-rule

要在每列之间添加一条垂直线,请声明 column-rule

此属性是 column-rule-widthcolumn-rule-stylecolumn-rule-color 的简写形式。简写形式遵循与 border 相同的样式模式。

article {
  -webkit-columns: 2 200px;
     -moz-columns: 2 200px;
          columns: 2 200px;
  -webkit-column-gap: 4em;
     -moz-column-gap: 4em;
          column-gap: 4em;
  -webkit-column-rule: 1px dotted #ddd;
     -moz-column-rule: 1px dotted #ddd;
          column-rule: 1px dotted #ddd;
}

实时演示

查看 Pen [6] CSS 列,column-rule 由 Katy DeCorah (@katydecorah) 在 CodePen 上。

column-gap 一样,垂直线在浏览器宽度过窄时将退出,如下面的 gif 所示。

column-rule drops as browser width narrows

column-span

要暂时打破列流动,请在子元素上声明 column-span。目前,Firefox 不支持此功能(但您可以去 Bugzilla 上投票)。

下图包含一个标题,表示故事中新章节的开始,但它继续进行列流动。

columns without a spanning element

要将标题从列流动中删除,请在元素上添加 column-span: all。此声明将暂时停止列流动以允许元素跨越列,但将在下一个元素处重新启动列。

h3 { 
  -webkit-column-span: all; 
          column-span: all; 
}

实时演示

查看 Pen [7] CSS 列,column-span 由 Katy DeCorah (@katydecorah) 在 CodePen 上。

column-fill

要更改内容填充列的方式,请声明 column-fill。目前,此属性仅在 Firefox 中可用。

当高度添加到列元素时,Firefox 的行为与其他浏览器不同。Firefox 会自动平衡内容,而其他浏览器会按顺序填充列。

下图演示了当高度添加到列元素时 Firefox 的行为与其他浏览器的行为对比。

difference between auto and balance

在 Firefox 中,您可以通过声明 column-fill: auto 来更改此行为。此规则将使列按顺序填充,如下面的实时演示所示。

article {
  -webkit-columns: 2 200px;
     -moz-columns: 2 200px;
          columns: 2 200px;
  -moz-column-fill: auto;
       column-fill: auto;
  height: 350px;
}

实时演示

查看 Pen [8] CSS Columns, column-fill 由 Katy DeCorah (@katydecorah) 在 CodePen 上创建。

由于 Firefox 必须声明高度才能启用 column-fill,因此高度约束打破了流体模式。内容会水平扩展,因为它无法像下面 gif 中演示的那样垂直流动。在这种情况下,可以添加媒体查询来管理高度(稍后将详细介绍)。

height restriction on column-fill

其他浏览器不支持 column-fill,并且在对列元素声明高度时会按顺序填充列。值得注意的是,当对任何列元素添加高度时,无论浏览器或是否使用 column-fill,约束都会打破流体模式。

局限性

只要内容保持可读,列就可以成为一种优雅的传递内容的方式。当内容水平溢出或列的高度超过视窗时,多列布局可能会变得难以阅读。

内容水平溢出

column-fill 部分所示,如果对列元素添加高度,则元素会水平扩展以适合内容。溢出会破坏布局并导致用户转向其他方向。

可能的解决方案:创建 min-width 媒体查询来声明高度规则。

在下面的演示中,我缩小了浏览器窗口,以找到列开始溢出时的位置,并记下了该数字。接下来,我使用列溢出时的值编写了一个 min-width 媒体查询,并将高度规则移到了媒体查询中。

article {
  -webkit-columns: 2 200px;
     -moz-columns: 2 200px;
          columns: 2 200px;
  -moz-column-fill: auto;
       column-fill: auto;
}
@media (min-width: 500px) {
  article {
    height: 350px;
  }
}

实时演示

查看 Pen [11] CSS Columns, column-fill height 由 Katy DeCorah (@katydecorah) 在 CodePen 上创建。

如下面 gif 中演示的那样,当列释放时,高度规则超出了界限,列会垂直流动。

height on min-width

列的高度超过视窗

如果您的列高度超出视窗,则用户需要滚动才能跟随列的流动。

可能的解决方案:创建 min-height 媒体查询以激活列。

在下面的示例中,只有当列元素具有 min-height: 400px; 时,列才会激活。我是通过缩小浏览器宽度,直到列即将释放,然后调整浏览器的高度,找到列开始低于视窗的位置,来得到这个数字的。我将该数字用作 min-height 媒体查询的值。

@media (min-height: 400px) {
  article {
    -webkit-columns: 2 350px;
       -moz-columns: 2 350px;
            columns: 2 350px;
  }
}

实时演示

查看 Pen [10] CSS Columns, vertical friendly 由 Katy DeCorah (@katydecorah) 在 CodePen 上创建。

下面的 gif 演示了列元素必须至少有 400px 高才能以列显示内容。

column on min-height only

支持

CSS 列具有良好的支持(IE10+),但所有属性仍然需要前缀。在 Can I Use… 上了解有关多列属性的更多详细信息。

即使您最喜欢的浏览器不支持多列布局,请记住它们会优雅地降级为单列布局。CSS 列就像内容传递的自动扶梯(正如米奇·赫德伯格所言)

mitch hedberg

多列布局不会中断,它只会变成单列布局。