【问题标题】:CSS Grid: Universal row column CSS rules which abstract away specific column and row countsCSS Grid:通用行列 CSS 规则,抽象出特定列和行数
【发布时间】:2022-01-11 20:12:16
【问题描述】:

我想利用 CSS Grid 来均匀地调整属于同一 CSS Grid 轴的那些元素:

[class*=' container-grid-'], [class^='container-grid-'] {
  /* give margin-bottom to all kinds of "container-grid-", see https://stackoverflow.com/a/13352103/923560 */
  margin-bottom: 2rem;
}

[class*=' container-grid-']  > .col, [class^='container-grid-'] > .col {
  display: contents;
}

.container-grid-2by2 {
  display: grid;
  grid-auto-flow: column;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(2, auto);
  row-gap: 0;
  column-gap: 1rem;
}


.container-grid-3by3 {
  display: grid;
  grid-auto-flow: column;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, auto);
  row-gap: 0;
  column-gap: 1rem;
}

.red {
  background-color: red;
}

.green {
  background-color: green;
}

.blue {
 background-color: skyblue;
}

.limit-width {
  max-width: 20rem;
  background-color: silver;
}
<div class="limit-width">

<h1><code>.container-grid-2by2</code></h1>

<div class="container-grid-2by2">
  <div class="col">
    <div class="red">
      Foo1
    </div>
    <div class="green">
      Bar1
    </div>
  </div>
  <div class="col">
    <div class="red">
      Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
    </div>
    <div class="green">
      Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
    </div>
  </div>
</div>

</div>


<div class="limit-width">

<h1><code>.container-grid-3by3</code></h1>

<div class="container-grid-3by3">
  <div class="col">
    <div class="red">
      Foo1
    </div>
    <div class="green">
      Bar1
    </div>
    <div class="blue">
      Baz1
    </div>
  </div>
  <div class="col">
    <div class="red">
      Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
    </div>
    <div class="green">
      Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
    </div>
    <div class="blue">
      Baz3
    </div>
  </div>
  <div class="col">
    <div class="red">
      Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
    </div>
    <div class="green">
      Bar3 Bar3 Bar3 Bar3 Bar3 Bar3 Bar3 Bar3 
    </div>
    <div class="blue">
      Baz3
    </div>
  </div>
</div>

</div>

如您所见,同一 CSS 网格行轴 上的元素具有相同的高度,例如文本内容很少 (Foo1) 的单元格会拉伸以匹配具有大多数文本内容的单元格的高度 (Foo2 Foo2 Foo2 ...)。太棒了,这正是我想要的!

HTML 遵循以下结构:&lt;div class="container-grid-*"&gt; 元素充当 CSS 网格容器;里面有几个&lt;div class="col"&gt;作为列;然后在这些列中的实际内容 HTML 元素。 .col 元素使用display: contents;CSS grid cell 确定“委托”到实际内容的HTML 元素。

但现在,我的 CSS 需要为每一列和每一行计数明确的规则:.container-grid-2by2.container-grid-3by3.container-grid-2by3.container-grid-3by2 等。

应该有办法重构这个,不是吗?

是否有任何 CSS 技巧可以自动导出 CSS 网格列数和行数?

在我的情况下,总是可以假设在一个容器中,每一列都有相同数量的实际 HTML 内容元素;例如在一个容器中,所有的列都会有 x 个元素。

【问题讨论】:

    标签: css-grid


    【解决方案1】:

    我发现了两个尚未完全概括的解决方案,并且依赖于变通方法和技巧。

    不太老套的解决方案

    在 Chrome 96 和 Firefox 94 中成功测试。

    此解决方案依赖于一组“预先计算”的 CSS 规则,将 nth-child(x) .col 子项放入 x 的网格行中。由于.container-grid 定义了一个完全隐式(相对于显式)CSS 网格,下一个.col 的第一个元素将自动引入下一列并放置在下一列中。

    .container-grid {
      display: grid;
      row-gap: 0;
      column-gap: 1rem;
      grid-auto-columns: 1fr;
    }
    
    .container-grid > .col {
      display: contents;
    }
    
    
    .container-grid > .col > div:nth-child(1) {
      grid-row: 1;
    }
    
    .container-grid > .col > div:nth-child(2) {
      grid-row: 2;
    }
    
    .container-grid > .col > div:nth-child(3) {
      grid-row: 3;
    }
    
    .container-grid > .col > div:nth-child(4) {
      grid-row: 4;
    }
    
    /* ... and so on up to the maximum amount of vertical grid elements you can imagine in each row */
    
    .red {
      background-color: red;
    }
    
    .green {
      background-color: green;
    }
    
    .blue {
      background-color: skyblue;
    }
    
    .yellow {
      background-color: yellow;
    }
    
    .limit-width {
      max-width: 30rem;
      background-color: silver;
    }
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 1col x 1row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
      </div>
    </div>
    
    </div>
    
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 1col x 2row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 2col x 1row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 2col x 2row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 2col x 3row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
        <div class="blue">
          Baz1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
        <div class="blue">
          Baz2
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 3col x 2row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
        </div>
        <div class="green">
          Bar3 Bar3 Bar3 Bar3 
        </div>
      </div>
    </div>
    
    </div>
    
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 3col x 3row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
        <div class="blue">
          Baz1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
        <div class="blue">
          Baz2
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
        </div>
        <div class="green">
          Bar3 Bar3 Bar3 Bar3
        </div>
        <div class="blue">
          Baz3 
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 4col x 3row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
        <div class="blue">
          Baz1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
        <div class="blue">
          Baz2
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
        </div>
        <div class="green">
          Bar3 Bar3 Bar3 Bar3
        </div>
        <div class="blue">
          Baz3 
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo4 
        </div>
        <div class="green">
          Bar4
        </div>
        <div class="blue">
          Baz4 
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 4col x 4row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
        <div class="blue">
          Baz1
        </div>
        <div class="yellow">
          Qux1 Qux1 Qux1 Qux1 Qux1 Qux1 Qux1 Qux1 Qux1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
        <div class="blue">
          Baz2
        </div>
        <div class="yellow">
          Qux2
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
        </div>
        <div class="green">
          Bar3 Bar3 Bar3 Bar3
        </div>
        <div class="blue">
          Baz3 
        </div>
        <div class="yellow">
          Qux3 Qux3 Qux3 Qux3 
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo4 
        </div>
        <div class="green">
          Bar4
        </div>
        <div class="blue">
          Baz4 
        </div>
        <div class="yellow">
          Qux4
        </div>
      </div>
    </div>
    
    </div>

    非常老套的解决方案

    在 Chrome 96 和 Firefox 94 中成功测试。

    此解决方案依赖于每个.col::after 伪元素:此伪元素占用/入侵足够多的grid-row 以溢出到下一个隐式列。 grid-auto-columns: 1fr 0; 中的 0 确保此幻像列不占用水平空间。

    此解决方案依赖于the hack to give an explicitly high value for the pseudo-element grid-row value

    .container-grid {
      display: grid;
      row-gap: 0;
      column-gap: 0.5rem; /* column-gap is created for both .col and pseudo-element phantom column, therefore to achieve an effective column-gap of 1rem, we use the half value of 0.5rem */
      grid-auto-flow: column;
      grid-auto-columns: 1fr 0; /* 1fr is for each .col, 0 is for its follow-up pseudo-element phantom column to occupy no horizontal space */ 
    }
    
    .container-grid > .col {
      display: contents;
    }
    
    .container-grid > .col::after {
      content: "";
      grid-row: span 8; /* span x, where x is the maximum amount of elements that will every be in a column */
      background-color: pink;
    }
    
    .container-grid > .col:only-child::after {
      /* ugly fix for the case of 1col x 1row and 1col x 2row */
      grid-row: 9; /* y, where y = x + 1, where x is the maximum amount of elements that will every be in a column */
    }
    
    .container-grid > .col:not(:first-child):last-child::after {
      /* last .col shall not create a follow-up pseudo-element phantom column
      content: unset; 
    }
    
    .red {
      background-color: red;
    }
    
    .green {
      background-color: green;
    }
    
    .blue {
      background-color: skyblue;
    }
    
    .yellow {
      background-color: yellow;
    }
    
    .limit-width {
      max-width: 30rem;
      background-color: silver;
    }
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 1col x 1row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
      </div>
    </div>
    
    </div>
    
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 1col x 2row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 2col x 1row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 2col x 2row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 2col x 3row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
        <div class="blue">
          Baz1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
        <div class="blue">
          Baz2
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 3col x 2row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
        </div>
        <div class="green">
          Bar3 Bar3 Bar3 Bar3 
        </div>
      </div>
    </div>
    
    </div>
    
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 3col x 3row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
        <div class="blue">
          Baz1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
        <div class="blue">
          Baz2
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
        </div>
        <div class="green">
          Bar3 Bar3 Bar3 Bar3
        </div>
        <div class="blue">
          Baz3 
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 4col x 3row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
        <div class="blue">
          Baz1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
        <div class="blue">
          Baz2
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
        </div>
        <div class="green">
          Bar3 Bar3 Bar3 Bar3
        </div>
        <div class="blue">
          Baz3 
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo4 
        </div>
        <div class="green">
          Bar4
        </div>
        <div class="blue">
          Baz4 
        </div>
      </div>
    </div>
    
    </div>
    
    
    <div class="limit-width">
    
    <h1><code>.container-grid</code> 4col x 4row</h1>
    
    <div class="container-grid">
      <div class="col">
        <div class="red">
          Foo1
        </div>
        <div class="green">
          Bar1
        </div>
        <div class="blue">
          Baz1
        </div>
        <div class="yellow">
          Qux1 Qux1 Qux1 Qux1 Qux1 Qux1 Qux1 Qux1 Qux1
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2 Foo2
        </div>
        <div class="green">
          Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2 Bar2
        </div>
        <div class="blue">
          Baz2
        </div>
        <div class="yellow">
          Qux2
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 Foo3 
        </div>
        <div class="green">
          Bar3 Bar3 Bar3 Bar3
        </div>
        <div class="blue">
          Baz3 
        </div>
        <div class="yellow">
          Qux3 Qux3 Qux3 Qux3 
        </div>
      </div>
      <div class="col">
        <div class="red">
          Foo4 
        </div>
        <div class="green">
          Bar4
        </div>
        <div class="blue">
          Baz4 
        </div>
        <div class="yellow">
          Qux4
        </div>
      </div>
    </div>
    
    </div>

    更新:似乎非常 hacky 的解决方案无法通过 运行代码 sn-p,但它可以在代码片段编辑器中工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      相关资源
      最近更新 更多