CSS网格行不按预期跨越

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

CSS grid row not spanning as expected

问题

我正在尝试将我的第二个网格项跨越两行。

我可以使用grid-row: span 2语法实现我想要的效果。但是我希望使用grid-row: x/y语法实现相同的结果,其中x和y是数字值。

问题是,第二种语法产生了意外的结果。
请有人帮助我理解我做错了什么?

结果

预期结果

我尝试阅读CSS以找出问题的原因,还尝试使用不同的值。

英文:

I am trying to span my second grid item over two rows.

I am able to achieve what I am looking for using the grid-row: span 2 syntax. However I would like to achieve the same result using the grid-row: x/y syntax, where x and y are numeric values.

Problem is, the second syntax is producing unexpected results.
May someone please help me understand what it is I am doing wrong?

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

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

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

body {
  font-family: Impact, Haettenschweiler, &#39;Arial Narrow Bold&#39;, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: rosybrown;
  background: #ffff;
}

.container {
  display: grid;
  max-width: 960px;
  padding: 10px;
  margin: 0;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
}

.item {
  background: steelblue;
  color: white;
  font-size: 20px;
  padding: 20px;
  border: skyblue 1px solid;
}

.item:nth-child(1) {
  grid-column: 1/3;
  background-color: springgreen;
}

.item:nth-child(2) {
  background-color: royalblue;
  grid-row: 1/3;
}

.item:nth-child(3) {
  background: darkred;
}

.item:nth-child(5) {
  grid-column: 1/4;
}

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

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;item&quot;&gt; item1 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item2 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item3 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item4 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item5 &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

Result:

<a href="https://i.stack.imgur.com/Rkkiq.png"><img src="https://i.stack.imgur.com/Rkkiq.png"></a>

Expected result:

<a href="https://i.stack.imgur.com/Bcirq.png"><img src="https://i.stack.imgur.com/Bcirq.png"></a>

I tried reading through the CSS to find the cause of the problem, and I also tried using different values.

答案1

得分: 2

Sure, here are the translated parts:

Solution

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

在第一个项目中添加 grid-row: 1,或者在第二个项目中添加 grid-column: 3

.item:nth-child(1) {
   grid-column: 1/3;
   grid-row: 1; /* 新增 */
 }

或者

.item:nth-child(2) {
   grid-row: 1/3;
   grid-column: 3; /* 新增 */
 }

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

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

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;  
  max-width: 960px;
  padding: 10px;
  margin: 0;
}

.item {
  background: steelblue;
  color: white;
  font-size: 20px;
  padding: 20px;
  border: skyblue 1px solid;
}

.item:nth-child(1) {
  grid-column: 1/3;
  background-color: springgreen;
  grid-row: 1; /* 新增 */
}

.item:nth-child(2) {
  background-color: royalblue;
  grid-row: 1/3;
  /* grid-column: 3; */ /* 新增 */
}

.item:nth-child(3) {
  background: darkred;
}

.item:nth-child(5) {
  grid-column: 1/4;
}

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

body {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: rosybrown;
  background: #ffff;
}

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

<div class="container">
  <div class="item"> item1 </div>
  <div class="item"> item2 </div>
  <div class="item"> item3 </div>
  <div class="item"> item4 </div>
  <div class="item"> item5 </div>
</div>

<!-- end snippet -->


Explanation

基于行的定位

首先要记住 grid-rowgrid-column 是以下属性的缩写:

  • grid-row-start / grid-row-end
  • grid-column-start / grid-column-end

项目 #1 被设置为跨越前两列。

.item:nth-child(1) {
   grid-column: 1/3;
 }

但它没有定义行。因此,grid-row 默认为 auto

项目 #2 被设置为跨越前两行。

.item:nth-child(2) {
   grid-row: 1/3;
}

但它没有定义列。因此,grid-column 默认为 auto

顺便说一句:因为显式网格仅定义了一行(grid-template-rows: auto),并且没有定义高度,项目 #2 实际上跨越了两行——一个显式行和一个隐式行——而不仅仅是一个,就像它显示的那样。(这个问题值得另一个问题来讨论。)

网格项目定位算法

网格项目布局过程由网格项目定位算法处理。在这个过程中的第一步之一是:

>1. 定位任何未自动定位的内容。

因此:

  • 项目 #1 获取其定义的列(行为 auto)。
  • 项目 #2 获取其定义的行(列为 auto)。

这就是项目 #2 如何放置在项目 #1 的上面的原因。已定义的行和列优先于未定义的行和列——后者受算法更多控制。

如顶部所述,最简单的解决方案是从过程中删除 auto 变量。您可以通过在第一个项目中添加 grid-row: 1,或者在第二个项目中添加 grid-column: 3 来实现这一点。

英文:

Solution

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

Add grid-row: 1 to the first item, or grid-column: 3 to the second item.

.item:nth-child(1) {
   grid-column: 1/3;
   grid-row: 1; /* new */
 }

OR

.item:nth-child(2) {
   grid-row: 1/3;
   grid-column: 3; /* new */
 }

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

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

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;  
  max-width: 960px;
  padding: 10px;
  margin: 0;
}

.item {
  background: steelblue;
  color: white;
  font-size: 20px;
  padding: 20px;
  border: skyblue 1px solid;
}

.item:nth-child(1) {
  grid-column: 1/3;
  background-color: springgreen;
  grid-row: 1; /* new */
}

.item:nth-child(2) {
  background-color: royalblue;
  grid-row: 1/3;
  /* grid-column: 3; */ /* new */
}

.item:nth-child(3) {
  background: darkred;
}

.item:nth-child(5) {
  grid-column: 1/4;
}

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

body {
  font-family: Impact, Haettenschweiler, &#39;Arial Narrow Bold&#39;, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: rosybrown;
  background: #ffff;
}

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

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;item&quot;&gt; item1 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item2 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item3 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item4 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item5 &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->


Explanation

Line-Based Placement

Let's start by keeping in mind that grid-row and grid-column are shorthand properties for:

  • grid-row-start / grid-row-end
  • grid-column-start / grid-column-end

CSS网格行不按预期跨越

Item #1 is set to span across the first two columns.

.item:nth-child(1) {
   grid-column: 1/3;
 }

But it has no rows defined. Therefore, grid-row defaults to auto.

Item #2 is set to span the first two rows.

.item:nth-child(2) {
   grid-row: 1/3;
}

But it has no columns defined. Therefore, grid-column defaults to auto.

Side note: Because the explicit grid has only one row defined (grid-template-rows: auto), and no height defined, Item #2 is actually spanning across two rows—one explicit, one implicit—not just one as it appears. (This matter is worthy of another question.)

CSS网格行不按预期跨越

The Grid Item Placement Algorithm

The grid item layout process is handled by the Grid Item Placement Algorithm. One of the first steps in the process is this:

>1. Position anything that's not auto-positioned.

Therefore:

  • Item #1 gets its defined columns (rows are auto).
  • Item #2 gets its defined rows (columns are auto).

This is how Item #2 gets placed above Item #1. Defined rows and columns have precedence over undefined rows and columns—the latter subject to more control by the algorithm.

As mentioned at the top, the simplest solution is to remove the auto variable from the process. You can do this by adding grid-row: 1 to the first item, or grid-column: 3 to the second item.


span

grid-row: 1 / 3 is shorthand for:

  • grid-row-start: 1
  • grid-row-end: 3

grid-row: span 2 is equivalent to grid-row: span 2 / auto, which is shorthand for:

  • grid-row-start: span 2
  • grid-row-end: auto

When you switch from grid-row: 1 / 3 to grid-row: span 2, you remove the grid-row-start: 1 component. In other words, you unlock the item from the first row. The algorithm now has more control, moving the item to its natural position.

答案2

得分: 0

你可以利用 grid-template-areasgrid-area,像这样:

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

body {
  font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: rosybrown;
  background: #ffff;
}

.container {
  display: grid;
  max-width: 960px;
  padding: 10px;
  margin: 0;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
  grid-template-areas:
      "item1 item1 item2"
      "item3 item4 item2"
      "item5 item5 item5";
}

.item {
  background: steelblue;
  color: white;
  font-size: 20px;
  padding: 20px;
  border: skyblue 1px solid;
}

.item:nth-child(1) {
  grid-area: item1;
  background-color: springgreen;
}

.item:nth-child(2) {
  background-color: royalblue;
  grid-area: item2;
}

.item:nth-child(3) {
  background: darkred;
  grid-area: item3;
}

.item:nth-child(4) {
  grid-area: item4;
}

.item:nth-child(5) {
  grid-area: item5;
}
<div class="container">
  <div class="item"> item1 </div>
  <div class="item"> item2 </div>
  <div class="item"> item3 </div>
  <div class="item"> item4 </div>
  <div class="item"> item5 </div>
</div>
英文:

You could take advantage of grid-template-areas & grid-area, like so:

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

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

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

body {
  font-family: Impact, Haettenschweiler, &#39;Arial Narrow Bold&#39;, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: rosybrown;
  background: #ffff;
}

.container {
  display: grid;
  max-width: 960px;
  padding: 10px;
  margin: 0;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto;
  grid-template-areas:
      &quot;item1 item1 item2&quot;
      &quot;item3 item4 item2&quot;
      &quot;item5 item5 item5&quot;
}

.item {
  background: steelblue;
  color: white;
  font-size: 20px;
  padding: 20px;
  border: skyblue 1px solid;
}

.item:nth-child(1) {
  grid-area: item1;
  background-color: springgreen;
}

.item:nth-child(2) {
  background-color: royalblue;
  grid-area: item2;
}

.item:nth-child(3) {
  background: darkred;
  grid-area: item3;
}

.item:nth-child(4) {
  grid-area: item4;
}

.item:nth-child(5) {
  grid-area: item5;
}

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

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;item&quot;&gt; item1 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item2 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item3 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item4 &lt;/div&gt;
  &lt;div class=&quot;item&quot;&gt; item5 &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月21日 02:40:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76296825.html
匿名

发表评论

匿名网友

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

确定