如何在子网格中使用CSS @container查询?

huangapple go评论82阅读模式
英文:

How to use CSS @container query with subgrid?

问题

以下是翻译好的部分:

Let's consider example of cards with only subgrid feature.

这是卡片仅包含子网格功能的示例。

This generates perfectly what I want (title, body, and footer are aligned vertically):

这完美地生成了我想要的效果(标题、正文和页脚垂直对齐):

Codesandbox for first implementation (https://codesandbox.io/s/silent-voice-cklrms), at the time of 23.07.2023 I suggest to open it in Chrome Canary or Firefox.

第一次实现的Codesandbox(https://codesandbox.io/s/silent-voice-cklrms),在2023年7月23日时,建议在Chrome Canary或Firefox中打开。

Problem

问题

When I try to add to my example CSS @container query I don't know how to keep the previous functionality of subgrid.

当我尝试在我的示例中添加CSS @container查询时,我不知道如何保持先前的子网格功能。

Consider this modification to HTML, addition of .card-outer-wrapper, reference why I had to add this wrapper:

考虑对HTML的这个修改,添加.card-outer-wrapper,参考为什么我必须添加这个包装器:

It properly shows background color on a wider card but it lacks subgrid functionality:

它正确显示了更宽的卡片的背景颜色,但缺乏子网格功能:

Here is the code sandbox for the second example: https://codesandbox.io/s/nifty-feynman-n42s5p

这是第二个示例的代码沙盒链接:https://codesandbox.io/s/nifty-feynman-n42s5p

Question

问题

How to modify my second example to achieve subgrid alignment and @container query together?

如何修改我的第二个示例以同时实现子网格对齐和@container查询?

Desired output should look like this:

期望的输出应该如下所示:

Highlight of desired vertical alignment:

期望的垂直对齐效果如下所示:

英文:

Let's consider example of cards with only subgrid feature.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

body {
  max-width: 500px;
  margin: 1rem auto;
}

.container {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-gap: 1rem;
}

.card {
  border: 1px solid #ccc;
  padding: 1rem;
  display: grid;
  grid-gap: 1rem;
  grid-row: span 3;
  grid-template-rows: subgrid;
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;card&quot;&gt;
    &lt;h2&gt;Title Similique quisquam nesciunt&lt;/h2&gt;
    &lt;p&gt;
      Body Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique quisquam nesciunt nihil totam laborum corporis animi expedita molestias, accusantium amet libero at neque id voluptatum, numquam, natus blanditiis eos sit!
    &lt;/p&gt;
    &lt;p&gt;Footer nesciunt nihil&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;card&quot;&gt;
    &lt;h2&gt;Title accusantium amet libero at neque&lt;/h2&gt;
    &lt;p&gt;
      Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
    &lt;/p&gt;
    &lt;p&gt;Footer dolor sit amet consectetur adipisicing elit&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

This generates perfectly what I want (title, body and footer are align vertically):

如何在子网格中使用CSS @container查询?

Codesanbox for first implementation (https://codesandbox.io/s/silent-voice-cklrms), at time of 23.07.2023 I suggest to open it in Chrome Canary or Firefox.


Problem

When I try to add to my example CSS @container query I don't know how to keep the previous functionality of subgrid.

Consider this modification to HTML, addition of .card-outer-wrapper, reference why I had to add this wrapper:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

body {
  max-width: 500px;
  margin: 1rem auto;
}

.container {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-gap: 1rem;
}

.card {
  border: 1px solid #ccc;
  padding: 1rem;
  display: grid;
  grid-gap: 1rem;
  grid-row: span 3;
  grid-template-rows: subgrid;
}

.card-outer-wrapper {
  container-type: inline-size;
}

@container (min-width: 300px) {
  .card {
    background-color: aqua;
  }
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;card-outer-wrapper&quot;&gt;
    &lt;div class=&quot;card&quot;&gt;
      &lt;h2&gt;Title Similique quisquam nesciunt&lt;/h2&gt;
      &lt;p&gt;
        Body Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique quisquam nesciunt nihil totam laborum corporis animi expedita molestias, accusantium amet libero at neque id voluptatum, numquam, natus blanditiis eos sit!
      &lt;/p&gt;
      &lt;p&gt;Footer nesciunt nihil&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;card-outer-wrapper&quot;&gt;
    &lt;div class=&quot;card&quot;&gt;
      &lt;h2&gt;Title accusantium amet libero at neque&lt;/h2&gt;
      &lt;p&gt;
        Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
      &lt;/p&gt;
      &lt;p&gt;Footer dolor sit amet consectetur adipisicing elit&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

It properly shows background color on wider card but it lacks of subgrid functionality:

如何在子网格中使用CSS @container查询?

Here is code sandbox for second example: https://codesandbox.io/s/nifty-feynman-n42s5p

Question

How to modify my second example to achieve subgrid alignment and @container query together?

Desired output should look like this:
如何在子网格中使用CSS @container查询?

Highlight of desired vertical alignment:
如何在子网格中使用CSS @container查询?

答案1

得分: 1

这是您要翻译的内容:

It is my understanding that what you are trying to do is currently not possible.

如果您在 grid-template-columns 和/或 grid-template-rows 上设置了值 subgrid嵌套的网格将使用其父级定义的轨道,而不是创建一个新的轨道列表。这允许两个兄弟嵌套的网格具有相同的结构。

容器查询 允许您根据元素容器的大小应用样式。换句话说,您可以将样式应用于容器的后代元素,而不是容器本身。

然而,当将包装器 div 添加为容器查询的容器元素时,包装器 div 是网格容器的子元素。 两个卡片 div 不再是兄弟元素,也不再共享相同的内部网格结构。

此外,通过测试,我发现**如果也在该元素上声明了 container-type,则子网格结构将丢失。因此,以下想法当前不会维护子网格结构:

.card {
  /* ... */
  grid-template-rows: subgrid;
  container-type: inline-size;
}

@container (min-width: 300px) {
  .card &gt; * {
    background-color: aqua;
    margin: 0;
    padding: 1rem;
  }
}

我想出了一个“hack”(解决方法)。如果知道网格容器的列是容器的多少分数,您可以计算网格容器必须有多宽才能使列成为目标宽度。因此,您可以通过将容器查询应用于网格容器并使用伪类(例如 :first-child:nth-child())来定位各个列,从而获得类似于所需容器查询的结果。

为网格容器声明 container-type。由于您使用的是 grid-template-columns: 2fr 1fr,第一列的宽度是网格容器的 2/3(不考虑填充和间隙,我不会处理)。因此,您可以计算容器的最小宽度值为第一列的目标最小宽度的 3/2 倍。最后,在容器查询中使用 :first-child 伪类来定位第一列。

(如果每一列都是 1fr,那么将每一列的目标最小宽度乘以列的数量,不需要使用伪类。)

3 / 2 * 300px = 450px

.container {
  container-type: inline-size;
}

@container (min-width: 450px) {
  .card:first-child {
    background-color: aqua;
  }
}


body {
max-width: 500px;
margin: 1rem auto;
}

.container {
container-type: inline-size;
display: grid;
grid-template-columns: 2fr 1fr;
grid-gap: 1rem;
}

.card {
border: 1px solid #ccc;
padding: 1rem;
display: grid;
grid-gap: 1rem;
grid-row: span 3;
grid-template-rows: subgrid;
}

@container (min-width: 450px) {
.card:first-child {
background-color: aqua;
}
}

Title Similique quisquam nesciunt

Body Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique quisquam nesciunt nihil totam laborum corporis animi expedita molestias, accusantium amet libero at neque id voluptatum, numquam, natus blanditiis eos sit!

Footer nesciunt nihil

Title accusantium amet libero at neque

Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?

Footer dolor sit amet consectetur adipisicing elit

英文:

It is my understanding that what you are trying to do is currently not possible.

If you set the value subgrid on grid-template-columns and/or grid-template-rows, the nested grid uses the tracks defined for its parent instead of creating a new track listing. This allows two sibling nested grids to have the same structure.

Container queries enable you to apply styles to an element based on the size of the element's container. In other words, you can apply styles to the descendent elements of the container, not the container itself.

However, when a wrapper div is added to be the container element for container queries, the wrapper div is the child of the grid container. The two card divs are no longer siblings and no longer share the same internal grid structure.

Additionally, I discovered through testing that the subgrid structure is lost if container-type is also declared on that element. Therefore, the following idea currently does not maintain subgrid structure:

.card {
  /* ... */
  grid-template-rows: subgrid;
  container-type: inline-size;
}

@container (min-width: 300px) {
  .card &gt; * {
    background-color: aqua;
    margin: 0;
    padding: 1rem;
  }
}

<hr><br>

I came up with a "hack" (workaround). If it's known what fraction of the grid container the column is, you can calculate how wide the grid container has to be in order for the column to be the targeted width. Therefore, you can get a result similar to the desired container query by applying the container query to the grid container and using pseudo-classes (such as :first-child, :nth-child()) to target individual columns.

Declare container-type for the grid container. Since you are using grid-template-columns: 2fr 1fr, the first column's width is 2/3 of the grid container (before factoring in padding and gap, which I won't address.) Therefore, you can calculate the min-width value of the container to be 3/2 times the targeted min-width of the first column. Finally, use the :first-child pseudo-class in the container query to target the first column.

(If every column is 1fr, then multiply the number of columns by the targeted min-width for each column and there's no need to use a pseudo-class.)

3 / 2 * 300px = 450px

.container {
  container-type: inline-size;
}

@container (min-width: 450px) {
  .card:first-child {
    background-color: aqua;
  }
}

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

body {
  max-width: 500px;
  margin: 1rem auto;
}

.container {
  container-type: inline-size;
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-gap: 1rem;
}

.card {
  border: 1px solid #ccc;
  padding: 1rem;
  display: grid;
  grid-gap: 1rem;
  grid-row: span 3;
  grid-template-rows: subgrid;
}

@container (min-width: 450px) {
  .card:first-child {
    background-color: aqua;
  }
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;card&quot;&gt;
    &lt;h2&gt;Title Similique quisquam nesciunt&lt;/h2&gt;
    &lt;p&gt;
      Body Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique quisquam nesciunt nihil totam laborum corporis animi expedita molestias, accusantium amet libero at neque id voluptatum, numquam, natus blanditiis eos sit!
    &lt;/p&gt;
    &lt;p&gt;Footer nesciunt nihil&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class=&quot;card&quot;&gt;
    &lt;h2&gt;Title accusantium amet libero at neque&lt;/h2&gt;
    &lt;p&gt;
      Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
    &lt;/p&gt;
    &lt;p&gt;Footer dolor sit amet consectetur adipisicing elit&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

答案2

得分: 1

根据您的要求,您需要计算卡片的宽度,并且还想更改该卡片的背景颜色。但根据@container的官方文档,我们不能直接更改应用容器类型属性的属性。所以,我做的是将卡片内的每个组件都包装在一个div标签中,并对该div标签使用了背景颜色。

我得到了以下答案:

更改了第一列的背景颜色

body {
  max-width: 500px;
  margin: 1rem auto;
}

.container {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-template-rows: auto;
  grid-gap: 1rem;
}

.card {
  container-type: inline-size;
  border: 1px solid #ccc;
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
}

.card div {
  padding: 1rem;
}

@container (min-width: 300px) {
  .card div {
    background-color: aqua !important;
  }
}
<div class="container">
  <div class="card">
    <div>
      <h2>Title Similique quisquam nesciunt</h2>
    </div>
    <div>
      <p>
        Body Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique quisquam nesciunt nihil totam laborum corporis animi expedita molestias, accusantium amet libero at neque id voluptatum, numquam, natus blanditiis eos sit!
      </p>
    </div>
    <div>
      <p>Footer nesciunt nihil</p>
    </div>
  </div>
  <div class="card">
    <div>
      <h2>Title accusantium amet libero at neque</h2>
    </div>
    <div>
      <p>
        Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
      </p>
    </div>
    <div>
      <p>Footer dolor sit amet consectetur adipisicing elit</p>
    </div>
  </div>
</div>

现在我更改了grid-template-columns为1fr 1fr 1fr,得到了以下结果:

更改grid-template-columns值为1fr 1fr 1fr后的结果

body {
  max-width: 500px;
  margin: 1rem auto;
}

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto;
  grid-gap: 1rem;
}

.card {
  container-type: inline-size;
  border: 1px solid #ccc;
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
}

.card div {
  padding: 1rem;
}

@container (min-width: 300px) {
  .card div {
    background-color: aqua !important;
  }
}
<div class="container">
  <div class="card">
    <div>
      <h2>Title Similique quisquam nesciunt</h2>
    </div>
    <div>
      <p>
        Body Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique quisquam nesciunt nihil totam laborum corporis animi expedita molestias, accusantium amet libero at neque id voluptatum, numquam, natus blanditiis eos sit!
      </p>
    </div>
    <div>
      <p>Footer nesciunt nihil</p>
    </div>
  </div>
  <div class="card">
    <div>
      <h2>Title accusantium amet libero at neque</h2>
    </div>
    <div>
      <p>
        Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
      </p>
    </div>
    <div>
      <p>Footer dolor sit amet consectetur adipisicing elit</p>
    </div>
  </div>
  <div class="card">
    <div>
      <h2>Title accusantium amet libero at neque</h2>
    </div>
    <div>
      <p>
        Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
      </p>
    </div>
    <div>
      <p>Footer dolor sit amet consectetur adipisicing elit</p>
    </div>
  </div>
</div>
</body>
英文:

According to your requirement, you have to calculate the width of the card and also want to change the background color of that card. But according to the official documentation of @container, we can't directly change the properties on which we apply container-type property. So, what I did is I wrapped every component inside the card with a div tag and used a background color to that div tag.

I got the answer like this

changed the background color of the first column

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

  body {
  max-width: 500px;
  margin: 1rem auto;
}
.container {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-template-rows: auto;
  grid-gap:1rem;
}

.card {
  container-type: inline-size;
  border: 1px solid #ccc;
  display: grid;
  grid-row:span 3;
  grid-template-rows:subgrid;
}

.card div{
  padding:1rem;
}

@container (min-width: 300px) {
  .card div {
    background-color: aqua !important;
  }
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
      &lt;div class=&quot;card&quot;&gt;
        &lt;div&gt;
        &lt;h2&gt;Title Similique quisquam nesciunt&lt;/h2&gt;
        &lt;/div&gt;
        &lt;div&gt;
        &lt;p&gt;
          Body Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique quisquam nesciunt nihil totam laborum corporis animi expedita molestias, accusantium amet libero at neque id voluptatum, numquam, natus blanditiis eos sit!
        &lt;/p&gt;
       &lt;/div&gt;
       &lt;div&gt;
        &lt;p&gt;Footer nesciunt nihil&lt;/p&gt;
       &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class=&quot;card&quot;&gt;
        &lt;div&gt;
        &lt;h2&gt;Title accusantium amet libero at neque&lt;/h2&gt;
       &lt;/div&gt;
       &lt;div&gt;
        &lt;p&gt;
          Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
        &lt;/p&gt;
       &lt;/div&gt;
       &lt;div&gt;
        &lt;p&gt;Footer dolor sit amet consectetur adipisicing elit&lt;/p&gt;
       &lt;/div&gt;
      &lt;/div&gt;

  &lt;/div&gt;

<!-- end snippet -->

now I changed grid-templete-columns: 1fr 1fr 1fr

I got this as the result
Result after changing the grid-templete-columns value to 1fr 1fr 1fr

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

body {
  max-width: 500px;
  margin: 1rem auto;
}

.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto;
  grid-gap:1rem;
}

.card {
  container-type: inline-size;
  border: 1px solid #ccc;
  display: grid;
  grid-row:span 3;
  grid-template-rows:subgrid;
}

.card div{
  padding:1rem;
}

@container (min-width: 300px) {
  .card div {
    background-color: aqua !important;
  }
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
    &lt;div class=&quot;card&quot;&gt;
      &lt;div&gt;
      &lt;h2&gt;Title Similique quisquam nesciunt&lt;/h2&gt;
      &lt;/div&gt;
      &lt;div&gt;
      &lt;p&gt;
        Body Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique quisquam nesciunt nihil totam laborum corporis animi expedita molestias, accusantium amet libero at neque id voluptatum, numquam, natus blanditiis eos sit!
      &lt;/p&gt;
     &lt;/div&gt;
     &lt;div&gt;
      &lt;p&gt;Footer nesciunt nihil&lt;/p&gt;
     &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;card&quot;&gt;
      &lt;div&gt;
      &lt;h2&gt;Title accusantium amet libero at neque&lt;/h2&gt;
     &lt;/div&gt;
     &lt;div&gt;
      &lt;p&gt;
        Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
      &lt;/p&gt;
     &lt;/div&gt;
     &lt;div&gt;
      &lt;p&gt;Footer dolor sit amet consectetur adipisicing elit&lt;/p&gt;
     &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class=&quot;card&quot;&gt;
     &lt;div&gt;
     &lt;h2&gt;Title accusantium amet libero at neque&lt;/h2&gt;
     &lt;/div&gt;
     &lt;div&gt;
      &lt;p&gt;
      Body Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quisquam minima ducimus numquam deleniti perspiciatis expedita nam commodi laboriosam illo! Blanditiis in dolorem eius. Hic assumenda architecto quidem magnam?
      &lt;/p&gt;
     &lt;/div&gt;
     &lt;div&gt;
     &lt;p&gt;Footer dolor sit amet consectetur adipisicing elit&lt;/p&gt;
     &lt;/div&gt;
    &lt;/div&gt;

&lt;/div&gt;
&lt;/body&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年7月23日 23:34:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76749065.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定