How to prevent grid row range from changing when column layout changes?
I have a 3 X 3 CSS Grid .
I have a string where I have three elements A
, B
and C
.
I want the element to C
have rowspan
of 2.
For this I use grid-row: 1 / span 2;
. It spans two lines, but fits in the first column, not just in the third column. I don't know why this is happening.
I want the C element to stay where it is in the HTML.
One way to fix this is to explicitly install grid-column: 3 / span 1
, which I don't want to do. I want the elements to be laid out the way they are in HTML.
Is there a way to suppress this behavior?
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: 1 / span 2;
background: orange;
}
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
source to share
Another way to solve it (This indicates the reason why it specifies a string for other elements):
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: 1 / span 2;
background: orange;
}
.b {
grid-row: 1;
}
<div class="grid-container">
<div class="b">
<h1>A</h1>
</div>
<div class="b">
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
And the reason for this behavior is that more restrictive elements are positioned first. Thus, the possibilities of the grid algorithm to achieve a solution are greater.
That is, the item that has a requirement will be placed first, items that do not have the last requirement.
Steps 2 (for item a ) and 4 (for other items) in this part of the spec
source to share
If only one gets the stock to the line number, he will be the first and stand there in the stream. To avoid this, other grid items must also be set to the defaut line.
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
div {
grid-row: 1;/* here is the basic fix but will set each item on first row */
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: 1 / span 2;
background: orange;
}
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
Otherwise, you also need to say which one grid-column
it should stand in.
.a {
grid-row: 1 / span 2;
grid-column:3;
background: orange;
}
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: 1 / span 2;
grid-column:3;
background: orange;
}
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
or let the auto-placement do its job by only setting the number of lines, which here is the most flexible way in my opinion with the minimum amount of css rules / selectors to set, too much grid kills the grid :), keep it simple:
.a {
grid-row: span 2;
background: orange;
}
with a few examples to allow .aclass to do its job without setting the column or row number to where to stand, it will just cover where it is put in the stream
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
}
h1 {
border: 2px solid;
padding: 0;
margin: 0;
font-size: 20px;
}
.a {
grid-row: span 2;
background: orange;
}
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
</div>
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div class="a">
<h1>B</h1>
</div>
<div>
<h1>C</h1>
</div>
</div>
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div>
<h1>C</h1>
</div>
<div>
<h1>D</h1>
</div>
<div>
<h1>E</h1>
</div>
<div class="a">
<h1>F</h1>
</div>
<div>
<h1>G</h1>
</div>
<div>
<h1>H</h1>
</div>
</div>
<hr/>
<div class="grid-container">
<div>
<h1>A</h1>
</div>
<div>
<h1>B</h1>
</div>
<div class="a">
<h1>C</h1>
</div>
<div>
<h1>D</h1>
</div>
<div>
<h1>E</h1>
</div>
<div>
<h1>F</h1>
</div>
<div>
<h1>G</h1>
</div>
<div>
<h1>H</h1>
</div>
</div>
source to share
Clearly something in the spec is causing this behavior. I'm not sure what it is yet. (Update: see @ Vals answer for an explanation.)
However, here's a fair and simple solution:
Instead:
.a {
grid-row: 1 / span 2;
}
Using:
.a {
grid-row-end: span 2;
}
From the specification:
grid-row-start
,grid-column-start
,grid-row-end
And propertiesgrid-column-end
determine the size and location of the grid within the grid elements by making the line of flight or nothing (automatic) to its placement grid, thus indicating embedded start, block start and end of the embedded block end edge of its grid area....
For example,
grid-column-end: span 2
indicates the second grid line in the final direction from the linegrid-column-start
.
Also, consider this one rule that gives you complete control and makes it all work:
.a {
grid-area: 1 / 3 / 3 / 4;
}
grid-area
The shorthand property parses values ββin the following order:
-
grid-row-start
-
grid-column-start
-
grid-row-end
-
grid-column-end
Note the counterclockwise direction, which is opposite to margin
and padding
.
source to share