英文:
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, '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;
}
.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 -->
<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 -->
<a href="https://i.stack.imgur.com/Rkkiq.png"><img src="https://i.stack.imgur.com/Rkkiq.png"></a>
<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-row
和 grid-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, '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
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
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.)
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-areas
和 grid-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, '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;
}
<!-- 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 -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论