How do I specify row heights in CSS Grid layout? - html

I have a CSS Grid Layout in which I want to make some (middle 3) rows stretch to their maximum size. I'm probably looking for a property similar to what flex-grow: 1 does with Flexbox but I can't seem to find a solution.
Note: This is intended for an Electron app only, so browser compatibility is not really a concern.
I have the following CSS Grid Layout:
.grid {
display: grid;
grid-template-columns: 1fr 1.5fr 1fr;
grid-gap: 10px;
height: calc(100vh - 10px);
}
.grid .box {
background-color: grey;
}
.grid .box:first-child,
.grid .box:last-child {
grid-column-start: 1;
grid-column-end: -1;
}
/* These rows should 'grow' to the max height available. */
.grid .box:nth-child(n+5):nth-child(-n+7) {
grid-column-start: 1;
grid-column-end: -1;
}
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Which creates the following grid:
When none of the boxes contain any content I would like the grid to look something like this:

One of the Related posts gave me the (simple) answer.
Apparently the auto value on the grid-template-rows property does exactly what I was looking for.
.grid {
display:grid;
grid-template-columns: 1fr 1.5fr 1fr;
grid-template-rows: auto auto 1fr 1fr 1fr auto auto;
grid-gap:10px;
height: calc(100vh - 10px);
}

There is also the need to specify the minimum height for the elements, otherwise if they have no content they will disappear.
:root{
--body-margin:10px;
}
body{
margin:var(--body-margin);
}
.grid {
display:grid;
grid-template-columns: 1fr 1.5fr 1fr;
grid-template-rows: auto auto 1fr 1fr 1fr auto auto;
grid-gap:10px;
height: calc(100vh - calc(2 * var(--body-margin)));
}
.grid div{
min-height:20px;
background-color: grey;
}
.grid
div:nth-child(n+5):nth-child(-n+7),
div:first-child,
div:last-child{
grid-column-start: 1;
grid-column-end: -1;
}
<div class="grid">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>

Use of repeat with grid
When boxes doesn't contain any content and If you want to get rid of the empty box spaces as well than you can use following.
grid-template-rows: repeat(2, auto) repeat(3, 1fr) repeat(2, auto);
Or more compact syntax as last two cell size will be by default auto if not defined:
grid-template-rows: repeat(2, auto) repeat(3, 1fr);
If you want some space in any case than you can use:
grid-template-rows: repeat(2, 10px) repeat(3, 1fr) repeat(2, 10px);
Finally CSS would be
.grid {
display: grid;
grid-template-columns: 1fr 1.5fr 1fr;
grid-template-rows: repeat(2, auto) repeat(3, 1fr);
grid-gap: 10px;
height: calc(100vh - 10px);
}

.periodic-table {
display: grid;
grid-template-columns: repeat(18, 60px);
grid-template-rows: repeat(7, 70px) 40px repeat(2, 70px);
grid-gap: 2px;
}
This code will create 18 columns each of them are 60px, and 7 rows of 70px 8th row will be 40px then again 9th and 10th row will be 70px.

Related

Resize elements in same grid column to fit

I have a CSS grid with several columns and many rows (I'm building a timetable view). The rows and columns are defined on the grid element itself, and then on the elements within the grid I set their column (always only one column) and their rows (might be more than one row).
An example is as follows:
.grid {
display: grid;
grid-template-rows: [row-a] 1fr [row-b] 1fr [row-c] 1fr [row-d] 1fr;
grid-template-columns: [col] 1fr;
flex-grow: 1;
}
.entry-one {
grid-column: col;
grid-row: row-a/row-d;
background-color: red;
}
.entry-two {
grid-column: col;
grid-row: row-b;
background-color: green;
}
<div class='grid'>
<div class='entry-one'>
Foobar
</div>
<div class='entry-two'>
Barfoo
</div>
</div>
Now, what I would like to have is that the elements resize themselves and flow nicely, such that they fit next to each other. I can mock this using width and margin on the elements:
.grid {
display: grid;
grid-template-rows: [row-a] 1fr [row-b] 1fr [row-c] 1fr [row-d] 1fr;
grid-template-columns: [col] 1fr;
flex-grow: 1;
}
.entry-one {
grid-column: col;
grid-row: row-a/row-d;
background-color: red;
width: 50%; /* ADDED */
}
.entry-two {
grid-column: col;
grid-row: row-b;
background-color: green;
width: 50%; /* ADDED */
margin-left: 50%; /* ADDED */
}
<div class='grid'>
<div class='entry-one'>
Foobar
</div>
<div class='entry-two'>
Barfoo
</div>
</div>
However this is not optimal, especially as the elements are inserted dynamically. Is there a way to have the elements size & align themselves automatically using CSS? I've tried to use display: flex on the entries, but that did not result in what I want (or maybe I forgot to add another rule).
Thank you for any ideas, and have a nice day!
I made this to see if that is what you are looking for
.grid{
display: flex;
grid-template-rows: [row-a] 1fr [row-b] 1fr [row-c] 1fr [row-d] 1fr;
grid-template-columns: [col] 1fr;
flex-grow: 1;
}
I just changed your display to flex and delete your margin-left: 50%; on the entry two, hope it is what you are looking for

Div inside grid not taking the alloted area

I have a container where I am using grid layout as show below
My HTML looks like this
<div class='pagelayout'>
<div class="tophalf">This div needs to occupy entire width of the page</div>
</div>
CSS looks like this
.pagelayout {
display: grid;
flex-grow: 1;
grid-template-columns: 70fr 30fr;
grid-template-rows: auto auto;
overflow: auto;
grid-template-areas:
'tophalf tophalf'
'leftside rightside'
}
.tophalf{
grid-area: tophalf;
}
Snippet:
.pagelayout {
display: grid;
flex-grow: 1;
grid-template-columns: 70fr 30fr;
grid-template-rows: auto auto;
overflow: auto;
grid-template-areas: 'tophalf tophalf' 'leftside rightside'
}
.tophalf {
grid-area: tophalf;
}
<div class='pagelayout'>
<div class="tophalf">This div needs to occupy entire width of the page</div>
</div>
But the div(This div needs to occupy entire width of the page) is only taking 70fr and the rest 30fr is left unused.
If I change the grid template like this, everythign is working fine.
.pagelayout {
display: grid;
flex-grow: 1;
grid-template-columns: 1fr;
grid-template-rows: auto;
overflow: auto;
grid-template-areas:
'tophalf tophalf'
'leftside rightside'
}
.tophalf{
grid-area: tophalf;
}
Snippet:
.pagelayout {
display: grid;
flex-grow: 1;
grid-template-columns: 1fr;
grid-template-rows: auto;
overflow: auto;
grid-template-areas: 'tophalf tophalf' 'leftside rightside'
}
.tophalf {
grid-area: tophalf;
}
<div class ='pagelayout'>
<div class ="tophalf">This div needs to occupy entire width of the page</div>
</div>
What is that I'm doing wrong in the first case?
grid-template-columns: 70fr 30fr; this means create two colums one which takes 70fr & other which takes 30fr
grid-template-columns: 70fr 30fr;
grid-template-rows: auto auto;
.pagelayout {
display: grid;
flex-grow: 1;
grid-template-columns: 70fr 30fr; /*this means create two colums one which takes 70fr & other which takes 30fr*/
grid-template-rows: auto;
overflow: auto;
outline:2px solid green;
}
.tophalf {
outline:2px solid red;
}
<div class='pagelayout'>
<div class="tophalf">This div needs to occupy entire width of the page</div>
</div>

Why doesn't this CSS grid create the right number of rows and columns?

This CSS grid creates 7 rows only, as you can see by using "Inspect tool" of the browser.
Why?
.grid {
display: grid;
grid-gap: 1em;
height: 100%;
}
.grid8x8 {
grid-template-rows: repeat(8, 1fr);
grid-template-columns: repeat(8, 1fr);
}
.element {
background-color: yellow;
}
<div class="grid grid8x8">
<div class="element" style="grid-row: 2 / 4; grid-column: 3 / 6;">TEST</div>
</div>
You have actually 8 rows. What you see with the inspector is the gap between the cells, so for 8 rows there are 7 gaps (red lines are gaps):
If you reduce the gap size, you'll notice how the rows appear:
Note the 8 rows:
Your problem is the grid cell overflowing all the other cells because there's not enough space, because your grid-gap is too high.
Try this:
.grid { display: grid; grid-gap: 1em; height: 70vh; }
.grid8x8 { grid-template-rows: repeat(8, 1fr); grid-template-columns: repeat(8, 1fr); }
.element { background-color: yellow; }
<div class="grid grid8x8">
<div class="element" style="grid-row: 2 / 4; grid-column: 3 / 6;">TEST</div>
</div>

My css grid layout doesn't fill its container on chrome. What's causing the loss of a fraction of a pixel?

The markup below works as expected on firefox (paragraph is 980px), but not on chrome (paragraph is 979.94px). Does anyone know how to prevent this from happening?
codepen example: https://codepen.io/isaacsgraphic/pen/jOVrrMO
body {
width: 980px;
background: #99c;
margin: 0 auto;
}
.row {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-column-gap: 20px;
background: white;
}
.content-wrap {
grid-column: span 12;
width: 100%
}
<div class="row">
<div class="content-wrap">
<p>Example paragraph which is 979.94px, not 980 like the row it's within</p>
</div>
</div>
here's a longer example which shows how this problem breaks my column layout on chrome: https://codepen.io/isaacsgraphic/pen/yLVJGqp
It seems that this is a rounding error in chrome. It is possible to recreate the problem with any layout which creates a recurring number sub-pixel fraction for column widths (like 3 or 12 column layouts with 980px), whereas numbers of columns which divide the width easily like 5 or 10 work without issues. The same issues can be caused by grid-column-gap numbers which don't divide nicely.
The simplest fix is to make sure the layout pixel width divides neatly into 12 (6 and 3 work too actually, since chrome can handle one or two decimal places)
body {
width: 984px;
background: #99c;
margin: 0 auto;
}
.row {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-column-gap: 18px;
background: white;
}
.content-wrap {
grid-column: span 12;
width: 100%
}
<div class="row">
<div class="content-wrap">
<p>Example paragraph which is fits the full width of the row it's within</p>
</div>
</div>
Maybe it is because of the different fonts different browsers use?

Does CSS grid allow row stacking when grid columns are unevenly sized?

I would like to use CSS Grid to create a set of unevenly sized content columns which, for smaller viewports, stack vertically instead of horizontally.
My starting point is this codepen, which has three repeated columns of equal size that stack when you change the size of the viewport (by making the browser window smaller, for example). That pen starts out looking like this:
When I halve the available screen space, it shrinks down to like this:
This automatic breaking behavior is achieved with the follow grid definition in CSS:
.wrapper-wrapper {
display: grid;
grid-template-columns: 1fr minmax(0, 1024px) 1fr;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr) ) ;
grid-column: 2/-2;
}
I modified this code to use unevenly sized columns in this codepen:
.layout {
display: grid;
grid-template-columns: 1fr minmax(0px, 1024px) 1fr;
}
.content {
grid-column: 2 / -2;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 3fr) minmax(200px, 4fr) minmax(200px, 3fr));
grid-gap: 10px;
}
But when I resize the browser window, instead of stacking in the rows like the first example, this example does the following:
But I want the following to happen:
The only difference between the first example and the second is that in the second, an unevenly sized grid column layout is used. If I modify the following line:
grid-template-columns: repeat(auto-fill, minmax(200px, 3fr) minmax(200px, 4fr) minmax(200px, 3fr));
And replace it with:
grid-template-columns: repeat(auto-fill, minmax(200px, 3fr));
As in the first example, it begins to do what I want again.
What do I need to do to preserve this behavior in the uneven columns case?
The problem code:
.layout {
display: grid;
grid-template-columns: 1fr minmax(0px, 1024px) 1fr;
}
.content {
grid-column: 2 / -2;
display: grid;
grid-template-columns: repeat(auto-fill,
minmax(200px, 3fr)
minmax(200px, 4fr)
minmax(200px, 3fr));
grid-gap: 10px;
}
.content-section {
background: lightblue;
}
.item-image {
width: 100%;
}
<div class="layout">
<div class="content">
<div class="content-section sidebar left-sidebar">
<div class="left-news-item">
<img src="https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png" class="item-image">
</div>
</div>
<div class="content-section content-main">
<div class="center-news-item">
<img src="https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png" class="item-image">
</div>
</div>
<div class="content-section sidebar right-sidebar">
<div class="left-news-item">
<img src="https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png" class="item-image">
</div>
</div>
</div>
</div>