Why does Chrome 80 cause this grid-template-rows: auto problem - html

Is anyone aware what is up with the latest Chrome 80 update?
Seems like
grid-template-rows: auto
started taking up some space from now even when a given row is not present in the markup. Happens on Chrome 80+ only.
.l-page {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: auto auto minmax(1px, 1fr);
/* // 1px is needed because of https://stackoverflow.com/questions/49558290/container-scrolls-to-top-when-children-element-height-changes */
grid-template-areas:
'sidebar primary_bar'
'sidebar notification'
'sidebar content';
width: 100vw;
height: 100vh;
}
.l-sidebar {
grid-area: sidebar;
padding-right: 10px;
}
.l-notification {
grid-area: notification;
}
.l-primary-bar {
grid-area: primary_bar;
}
.l-content {
grid-area: content;
}
<div class="l-page">
<div class="l-sidebar">sidebar</div>
<!--<div class="l-notification"></div>
<div class="l-primary-bar"></div>-->
<div class="l-content">content</div>
</div>
See also: https://jsfiddle.net/ju4xvegf/
Chrome 80
Firefox 72

I am not sure if it's a bug or something has changed in the CSS grid algorithm (need to revise the Spec) but you can simplify your logic like below:
.l-page {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto auto minmax(0, 1fr);
height: 300px;
margin:5px;
border: 1px solid red;
}
.l-sidebar {
grid-row: span 3;
grid-column:-3;
padding-right: 10px;
}
.l-primary-bar {
order: 1;
}
.l-notification {
order: 2;
}
.l-content {
order: 3;
}
<div class="l-page">
<div class="l-sidebar">sidebar</div>
<div class="l-content">content</div>
</div>
<div class="l-page">
<div class="l-sidebar">sidebar</div>
<div class="l-notification">notif</div>
<div class="l-primary-bar">bar</div>
<div class="l-content">content</div>
</div>
<div class="l-page">
<div class="l-sidebar">sidebar</div>
<div class="l-notification">notif</div>
<div class="l-content">content</div>
</div>
<div class="l-page">
<div class="l-primary-bar">bar</div>
<div class="l-notification">notif</div>
<div class="l-sidebar">sidebar</div>
<div class="l-content">content</div>
</div>
<div class="l-page">
<div class="l-primary-bar">bar</div>
<div class="l-notification">notif</div>
<div class="l-content">content</div>
</div>
UPDATE
With your initial code, if you change minmax(1px,1fr) with only 1fr it should work fine.
.l-page {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: auto auto 1fr;
grid-template-areas:
'sidebar primary_bar'
'sidebar notification'
'sidebar content';
height: 300px;
margin:5px;
border: 1px solid red;
}
.l-sidebar {
grid-area: sidebar;
padding-right: 10px;
}
.l-notification {
grid-area: notification;
}
.l-primary-bar {
grid-area: primary_bar;
}
.l-content {
grid-area: content;
}
<div class="l-page">
<div class="l-sidebar">sidebar</div>
<div class="l-content">content</div>
</div>
<div class="l-page">
<div class="l-sidebar">sidebar</div>
<div class="l-notification">notif</div>
<div class="l-primary-bar">bar</div>
<div class="l-content">content</div>
</div>
<div class="l-page">
<div class="l-sidebar">sidebar</div>
<div class="l-notification">notif</div>
<div class="l-content">content</div>
</div>
<div class="l-page">
<div class="l-primary-bar">bar</div>
<div class="l-notification">notif</div>
<div class="l-sidebar">sidebar</div>
<div class="l-content">content</div>
</div>
<div class="l-page">
<div class="l-primary-bar">bar</div>
<div class="l-notification">notif</div>
<div class="l-content">content</div>
</div>
It seems that the new version of chrome is resolving the minmax(1px,1fr) differently. You can try to increase the value of 1px slowly and notice how the minmax() will make the row bigger.
Note that 1fr is equivalent to minmax(auto,1fr) https://github.com/w3c/csswg-drafts/issues/1777
Related question having a similar issue: grid-template-columns in Chrome 80 inconsistently computed

NB: I'm distracted while writing this answer, and I haven't dived into CSS Grid in a while, so this is just my best guess as to what's going on.
I think this is related to your named grid-template-areas as well, not just your grid-template-rows setting. You have the following named areas in your CSS:
grid-template-areas:
'sidebar primary_bar'
'sidebar notification'
'sidebar content';
But in your markup, you have two of those right-column divs commented out:
<!--<div class="l-notification"></div>
<div class="l-primary-bar"></div>-->
Firefox, and Chrome prior to v80, appear to have ignored grid-template-areas that are empty or don't exist in the markup, hence why you see content on the same row as sidebar at the top. However, it looks like Chrome v80 has decided that, since you have declared multiple rows via your grid-template-areas property, it should reserve at least one row of space, perhaps using the following logic:
"collapse all empty rows into one row, then start rows with content on the next available row in the grid"
rather than what Chrome 79 (and Firefox 72) does:
"collapse all empty rows completely so that only rows with contents appear."
In short, you need to remove one of the named areas in your grid-template-areas property that you don't have markup for. I'll keep looking.

Related

CSS Grid minmax with auto as min

I'm wanting to have a grid with two columns where the leftmost column will scale based on the width of its content, but will not exceed 33% of the grid width.
However, it appears that grid-template-columns: minmax(auto, 33%) auto does not work as intended. The leftmost column is always at 33% width even if the content is smaller.
I'm probably misunderstanding what minmax is supposed to accomplish. Is there some other way to achieve what I'm trying to do?
.main {
display: grid;
grid-template-columns: minmax(auto, 33%) auto
}
.firstcol {
background: lightgreen;
}
.secondcol {
background: lightblue;
}
<div class="main">
<div class="firstcol">Short text</div>
<div class="secondcol">Some more text</div>
</div>
<hr />
<div class="main">
<div class="firstcol">This text is wayyyyyy to long and it should be wrapped</div>
<div class="secondcol">Some more text</div>
</div>
What about using grid-template-columns: fit-content(33%) 1fr
.main {
display: grid;
grid-template-columns: fit-content(33%) 1fr;
}
.firstcol {
background: lightgreen;
}
.secondcol {
background: lightblue;
}
<div class="main">
<div class="firstcol">Short text</div>
<div class="secondcol">Some more text</div>
</div>
<hr />
<div class="main">
<div class="firstcol">This text is wayyyyyy to long and it should be wrapped</div>
<div class="secondcol">Some more text</div>
</div>

CSS Grid: auto height including 1 column with multiple content blocks?

I've checked out https://gridbyexample.com/example and have been trying myself to make this work, but can't get it to fit right. Check out the attached image for what I'm trying to do. Is there an easy CSS-Grid way to do this?
What I have so far for CSS:
.main-container {
display: grid;
grid-gap: 15px;
grid-template-columns: repeat(auto-fit, minmax(225px, 1fr));
}
.box {
height: min-content;
}
/* Targeting the 2nd content block in column 3 */
.box.d {
grid-column: 3/6;
}
What I have so far for HTML:
<div class="main-container">
<div class=-"box a">Content Here</div>
<div class=-"box b">Content Here</div>
<div class=-"box c">Content Here</div>
<div class=-"box d">Content Here</div>
<div class=-"box e">Content Here</div>
<div class=-"box f">Content Here</div>
<div>
I think this is what you're looking for:
codepen
.main-container {
display: grid;
grid-gap: 15px;
grid-template-columns: repeat(auto-fit, minmax(225px, 1fr));
grid-template-rows: 2fr 2fr 1fr;
background: #ccc;
padding: 20px;
width: 1200px;
}
.box {
background: #fff;
padding: 20px;
}
.box.d {
grid-area: 2 / 3 / 4 / 3;
}
.box.b {
grid-area: 1 / 2 / 3 / 3;
}
<div class="main-container">
<div class="box a">Content Here</div>
<div class="box b">Content Here</div>
<div class="box c">Content Here</div>
<div class="box d">Content Here</div>
<div class="box e">Content Here</div>
<div class="box f">Content Here</div>
<div>
But it sometimes depends on the content of the columns.

Why are some grid items appearing out of order?

I am working on a CSS grid layout that looks something like this: https://jsfiddle.net/ftL5zw0x/23/ where I don't know how many items I will have.
The layout looks how I want it to but the problem is with the ordering. Every 6th and 7th items appear out of order, they should switch places while the layout stays unchanged. (For example items 6 and 7)
Is there any way I can achieve this through CSS alone?
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
grid-gap: 8px;
}
.item {
background-color: #c4c4c4;
display: flex;
justify-content: center;
align-items: center;
}
div:nth-child(8n+1),
div:nth-child(8n+3),
div:nth-child(8n+7),
div:nth-child(8n+8) {
grid-row: span 1;
}
div:nth-child(8n+2),
div:nth-child(8n+4),
div:nth-child(8n+5),
div:nth-child(8n+6) {
grid-row: span 2;
}
<div class="wrapper">
<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 class="item">item6</div>
<div class="item">item7</div>
<div class="item">item8</div>
<div class="item">item9</div>
<div class="item">item10</div>
<div class="item">item11</div>
<div class="item">item12</div>
<div class="item">item13</div>
<div class="item">item14</div>
<div class="item">item15</div>
<div class="item">item16</div>
</div>
First change your selectors that is the 7th element that should span not the 6th
This will push the 6th element to the right following the flow of the grid that is being the position of the previous element 5th
However we can enforce the position of every 6th element because we know it's the second column.
That will make the 7th and 8th element follow the 6th element we can fix this with grid-auto-flow:row dense;
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
grid-auto-flow: row dense;
grid-gap: 8px;
}
.item {
background-color: #c4c4c4;
display: flex;
justify-content: center;
align-items: center;
}
div:nth-child(8n+1),
div:nth-child(8n+3),
div:nth-child(8n+6),
div:nth-child(8n+8) {
grid-row: span 1;
}
div:nth-child(8n+2),
div:nth-child(8n+4),
div:nth-child(8n+5),
div:nth-child(8n+7) {
grid-row: span 2;
}
div:nth-child(8n+6) {
grid-column: 2;
}
<div class="wrapper">
<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 class="item">item6</div>
<div class="item">item7</div>
<div class="item">item8</div>
<div class="item">item9</div>
<div class="item">item10</div>
<div class="item">item11</div>
<div class="item">item12</div>
<div class="item">item13</div>
<div class="item">item14</div>
<div class="item">item15</div>
<div class="item">item16</div>
</div>
Although every 6th and 7th item appear out of order, they are not out of order.
Look at item 5 (a span 2 item). The top half is on row 2 and the bottom half is on row 3. But it gets placed on row 2.
Same for item 6. The top half is on row 2 and the bottom half is on row 3. It gets placed on row 2, which comes before row 3, which is where item 7 gets placed.
So, 6 is placed before 7, 15 is before 16, etc., and everything is placed in order.
Targeting these items with CSS is not a big deal.
div:nth-child(8n+6),
div:nth-child(8n+7) {}
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
grid-gap: 8px;
}
.item {
background-color: #c4c4c4;
display: flex;
justify-content: center;
align-items: center;
}
div:nth-child(8n+1), div:nth-child(8n+3), div:nth-child(8n+7), div:nth-child(8n+8) {
grid-row: span 1;
}
div:nth-child(8n+2), div:nth-child(8n+4), div:nth-child(8n+5), div:nth-child(8n+6) {
grid-row: span 2;
}
div:nth-child(8n+6),
div:nth-child(8n+7) {
background-color: lightgreen;
}
<div class="wrapper">
<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 class="item">item6</div>
<div class="item">item7</div>
<div class="item">item8</div>
<div class="item">item9</div>
<div class="item">item10</div>
<div class="item">item11</div>
<div class="item">item12</div>
<div class="item">item13</div>
<div class="item">item14</div>
<div class="item">item15</div>
<div class="item">item16</div>
</div>
But then what? Not sure there's any easy solution to the problem, but this one looks quite good.

CSS grid create not equal grid

started using CSS grid instead of boostrap, and im having some issue to get it right.
i want to create a grid layout that have 4fr, and 8fr columns (just like boostrap 8 and 4 columns)
and when the divs inside the grid of 4r gets fill its the divs go to a second row just like flex-wrap:wrap.
BUT Its not work its only push it inline one after another, and ignoring the grid boundaries
.home {
display: grid;
grid-template-columns: 4fr 8fr;
grid-template-rows: 100%;
height: 100%;
}
<div class="home">
<div class="col-8">
</div>
<div class="col-4">
<mat-button-toggle-group class="side-menu-button">
<mat-button-toggle>test </mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
</mat-button-toggle-group>
</div>
</div>
i even tried changing it to
grid-template-columns: repeat(1, auto-fill, 4fr 8fr);
If you're just wanting to use the grid to have items wrap inside of a div, what you're doing should basically work. Don't forget to tell .col-8 and .col-4 where they belong inside of the grid you've set up, and set the children you want to wrap to inline-block:
* {
box-sizing: border-box;
}
.home {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 100%;
height: 100%;
width: 100%;
grid-gap: 20px;
}
.col-8 {
grid-area: 1/1/1/9;
}
.col-4 {
grid-area: 1/9/1/13;
}
.bluebox,
.blackbox {
display: inline-block;
width: 50px;
height: 20px;
}
.bluebox {
background-color: blue;
}
.blackbox {
background-color: black;
}
<div class="home">
<div class="col-8">
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
</div>
<div class="col-4">
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
</div>
</div>
The reason I set up 12 columns instead of one that's 8fr and one that's 4fr is because I'm unclear about whether you're wanting a 12 column usable system like bootstrap (which is the way I implemented it), or literally only two columns. Either way should function for what you are describing in your question, but 12 separate columns is arguably more extensible later-on.
Here's a pen that contains the above code:
https://codepen.io/grantnoe/pen/MdOQOv
grid-area is what I used to set the location of .home's children. The format is as follows:
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
The only caveat is that you've nested the children you're wanting to wrap inside of secondary element <mat-button-toggle-group>. Consider adjusting the width of that element to 100% to fill the grid's child .col-4.

Why are my template areas not stacking as I expect?

Using the following css:
.container {
display : grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-template-areas:
'first second'
'first second'
;
}
.first {
grid-area: first;
width: 200px;
height: 200px;
background-color: red;
}
.second {
grid-area: second;
width: 200px;
height: 200px;
background-color: #0eb5d6;
These boxes will stack (appearing as one red, 1 blue):
<div class="container">
<div class="first"></div>
<div class="second"></div>
<div class="first"></div>
<div class="second"></div>
</div>
However, these will not stack, and correctly appear as 2 rows with the same css:
<div class="container">
<div class="first"></div>
<div class="second"></div>
</div>
<div class='container'>
<div class="first"></div>
<div class="second"></div>
</div>
In my actual use case I'm trying to align a form using css grid. I would like to not need divs for rows if possible. Or is this the only way to avoid stacking of elements into one row?
Note that here grid-template-areas form a rectangle and so first and second spans their columns. And multiple declaration will only overlap:
A row is created for every separate string listed, and a column is
created for each cell in the string. Multiple named cell tokens within
and between rows create a single named grid area that spans the
corresponding grid cells. Unless those cells form a rectangle, the
declaration is invalid.
MDN
You can remove grid-template-areas here - it works fine without it. See demo below:
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.first {
width: 200px;
height: 200px;
background-color: red;
}
.second {
width: 200px;
height: 200px;
background-color: #0eb5d6;
}
<div class="container">
<div class="first"></div>
<div class="second"></div>
<div class="first"></div>
<div class="second"></div>
</div>