在CSS网格中更改列顺序。

56

我正在尝试使用CSS网格布局。

当我在桌面尺寸 (min-width: 769px) 查看时,我有一行三列。就像这样:

---------------------------------------------
|   col 1     |         col 2       | col 3 |
|             |                     |       |
---------------------------------------------

我能否使用CSS网格移动列,以便在移动布局上执行以下操作?

---------------------------------------------
|     col 1             |      col 3        |
|                       |                   |
---------------------------------------------
|                     col 2                 |
---------------------------------------------

我知道可以使用类似以下的方式跨越单元格:

.content {
  grid-column: 1 / span2;
}

但我想改变列的顺序。我能在没有预处理器的情况下做到这一点吗?

这是我的当前网格类:

.my-grid {
   display: grid;
   grid-template-columns: 15% 1fr 25%;
   grid-template-rows: 1fr; /* For as many rows as you need */
   grid-gap: 10px;
   border: 2px solid #222;
   box-sizing: border-box;
}

4
CSS Grid似乎支持flexbox中使用的order属性。https://gridbyexample.com/examples/example23/ - sol
是的,那个可以用,我之前遇到了列跨度的问题,但现在也解决了。 - jwknz
很好。我对网格不是特别熟悉,所以无法提供更多帮助。 - sol
1个回答

128

网格布局提供了多种重新排列网格项的方法,下面列出了四种。

  1. grid-template-areas 属性
  2. 基于线的放置方式
  3. order 属性
  4. grid-auto-flow 属性的dense 函数(可能是此类型布局的最简单、最易用且最稳健的解决方案,因为它适用于任何数量的网格项。)

以下是原始布局:

grid-container {
  display: grid;
  grid-template-columns: 15% 1fr 25%;
  grid-auto-rows: 50px; /* for demo */
  grid-gap: 10px;
}

/* non-essential decorative styles */
grid-item {
  border: 1px solid gray;
  background-color: lightgreen;
  display: flex;
  align-items: center;
  justify-content: center;
}
grid-item:nth-child(2) {
  background-color: orange;
}
<grid-container>
  <grid-item>1</grid-item>
  <grid-item>2</grid-item>
  <grid-item>3</grid-item>
</grid-container>

jsFiddle演示1


1. grid-template-areas 属性

grid-template-areas 属性允许您使用 ASCII 艺术来排列布局。

将网格区域名称(为每个元素定义)放置在您希望它们出现的位置。

grid-container {
  display: grid;
  grid-template-columns: 15% 1fr 25%;
  grid-auto-rows: 50px; /* for demo */
  grid-gap: 10px;
  grid-template-areas: "column-1 column-2 column-3";
}

grid-item:nth-child(1) { grid-area: column-1; }
grid-item:nth-child(2) { grid-area: column-2; }
grid-item:nth-child(3) { grid-area: column-3; }

@media ( max-width: 500px ) {  
  grid-container { 
        grid-template-columns: 1fr 1fr; 
        grid-template-areas: " column-1 column-3 " 
                             " column-2 column-2 ";
   }
}

/* non-essential decorative styles */
grid-item {
  border: 1px solid gray;
  background-color: lightgreen;
  display: flex;
  align-items: center;
  justify-content: center;
}
grid-item:nth-child(2) {
  background-color: orange;
}
<grid-container>
  <grid-item>1</grid-item>
  <grid-item>2</grid-item>
  <grid-item>3</grid-item>
</grid-container>

jsFiddle演示2

根据规范:

7.3. 命名区域: grid-template-areas 属性

此属性指定命名网格区域,这些区域与任何特定的网格项都没有关联,但可以从“网格放置属性”中引用。

grid-template-areas属性的语法还提供了网格结构的可视化,使网格容器的整体布局更易于理解。

所有字符串必须具有相同的列数,否则声明无效。

如果一个命名网格区域跨越多个网格单元格,但这些单元格不形成单个填充的矩形,则该声明无效。

注意:在此模块的将来版本中可能允许非矩形或不连续区域。


2. 基于线条的放置

使用 grid-row-startgrid-row-endgrid-column-startgrid-column-end 或其缩写形式 grid-rowgrid-column,设置网格项在网格中的大小和位置。

grid-container {
  display: grid;
  grid-template-columns: 15% 1fr 25%;
  grid-auto-rows: 50px; /* for demo */
  grid-gap: 10px;
}

@media ( max-width: 500px ) {  
  grid-container         { grid-template-columns: 1fr 1fr;  }
  grid-item:nth-child(1) { grid-row: 1 / 2; grid-column: 1 / 2; }
  grid-item:nth-child(2) { grid-row: 2 / 3; grid-column: 1 / 3; }
  grid-item:nth-child(3) { grid-row: 1 / 2; grid-column: 2 / 3; }
}

/* non-essential decorative styles */
grid-item {
  border: 1px solid gray;
  background-color: lightgreen;
  display: flex;
  align-items: center;
  justify-content: center;
}
grid-item:nth-child(2) {
  background-color: orange;
}
<grid-container>
  <grid-item>1</grid-item>
  <grid-item>2</grid-item>
  <grid-item>3</grid-item>
</grid-container>

jsFiddle演示3

从规范中:

8.3. 基于线的放置:grid-row-start、grid-column-start、grid-row-end 和 grid-column-end 属性


3. order 属性

在Grid布局中,order 属性与Flex布局中相同。

grid-container {
  display: grid;
  grid-template-columns: 15% 1fr 25%;
  grid-auto-rows: 50px; /* for demo */
  grid-gap: 10px;
}

@media ( max-width: 500px ) {  
  grid-container         { grid-template-columns: 1fr 1fr;  }
  grid-item:nth-child(1) { order: 1; }
  grid-item:nth-child(2) { order: 3; grid-column: 1 / 3; }
  grid-item:nth-child(3) { order: 2; }
}

/* non-essential decorative styles */
grid-item {
  border: 1px solid gray;
  background-color: lightgreen;
  display: flex;
  align-items: center;
  justify-content: center;
}
grid-item:nth-child(2) {
  background-color: orange;
}
<grid-container>
  <grid-item>1</grid-item>
  <grid-item>2</grid-item>
  <grid-item>3</grid-item>
</grid-container>

jsFiddle演示3

来自规范:

6.3. 重排网格项: order 属性


4. grid-auto-flow 属性的 dense 函数

这个解决方案可能是所有方案中最简单、最易于理解和最健壮的,因为它适用于任何数量的网格项。

虽然在问题描述的布局中只包含三个网格项时,这个解决方案与前三个方案相比没有太大优势,但在网格项数目较多或动态生成时,它具有巨大的好处。

本问题及以上解决方案都在解决此问题:

01  03
02  02

但是假设我们需要这个:

01  03
02  02

04  06
05  05

07  09
08  08

10  12
11  11

and so on...

使用grid-template-areas、基于行的定位和order,如果我们知道总项目数,则解决方案将需要大量硬编码,可能还需要使用CSS自定义属性和/或JavaScript(如果项目是动态生成的)。

CSS Grid的dense函数可以轻松处理这两种情况。

通过将grid-auto-flow: dense应用于容器,每个第三个项目将填充由于连续排序而创建的空单元格。

grid-container {
  display: grid;
  grid-template-columns: 15% 1fr 25%;
  grid-auto-rows: 50px;
  grid-gap: 10px;
}

@media (max-width: 500px) {
  grid-container {
    grid-template-columns: 1fr 1fr;
    grid-auto-flow: dense;     /* KEY RULE; deactive to see what happens without it;
                                  defaults to "sparse" (consecutive ordering) value */
  }
  grid-item:nth-child(3n + 2) {
    grid-column: 1 / 3;
  }
}

/* non-essential decorative styles */
grid-item {
  border: 1px solid gray;
  background-color: lightgreen;
  display: flex;
  align-items: center;
  justify-content: center;
}
grid-item:nth-child(-n + 3)                    { background-color: aqua; }
grid-item:nth-child(n + 4):nth-child(-n + 6)   { background-color: lightgreen; }
grid-item:nth-child(n + 7):nth-child(-n + 9)   { background-color: orange; }
grid-item:nth-child(n + 10):nth-child(-n + 12) { background-color: lightgray; }
<grid-container>
  <grid-item>1</grid-item>
  <grid-item>2</grid-item>
  <grid-item>3</grid-item>
  <grid-item>4</grid-item>
  <grid-item>5</grid-item>
  <grid-item>6</grid-item>
  <grid-item>7</grid-item>
  <grid-item>8</grid-item>
  <grid-item>9</grid-item>
  <grid-item>10</grid-item>
  <grid-item>11</grid-item>
  <grid-item>12</grid-item>
</grid-container>

jsFiddle演示4

从规范中:

§7.7. 自动布局: grid-auto-flow属性

dense

如果指定,自动布局算法将使用“密集”装箱算法, 如果较小的项稍后出现,则尝试更早地填补网格中的空洞。

如果省略,则使用“稀疏”算法,其中仅在放置项时放置算法 “向前”移动,永远不会回溯来填充空洞。


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