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

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.

Related

Having problems with fitting content in div with css grid

I'm playing around with Css Grid and having problems with fitting overlaying content.
There is a top level container defined as css grid (class="container"), then content grid (class="content") which splits into 3 rows (header, label, rows).
Header is just a header, label contains labels for rows and rows is a content of "table".
Here is what it looks like:
When I resize window I got scroll bar on the right but it's for the whole page. Instead I would like to scroll only rows not the whole page.
Here is the the StackBlitz working example:
https://stackblitz.com/edit/angular-ivy-ayujp5
I guess it's simple but having problems with understanding how height is calculated and where and how overflow properties should be defined.
p {
font-family: Lato;
}
.container {
display: grid;
grid-template-columns: 30px 1fr 30px;
grid-template-rows: 30px 1fr 30px;
grid-template-areas: '. . .' '. content .' '. . .';
}
.content {
grid-area: content;
display: grid;
grid-template-rows: 50px 30px 1fr;
grid-template-areas: 'header' 'label' 'rows';
}
.header {
grid-area: header;
}
.label {
grid-area: label;
display: grid;
grid-template-rows: 1fr;
grid-template-columns: repeat(3, 4fr);
align-items: center;
}
.rows {
grid-area: rows;
height: 100%;
}
.row {
background-color: pink;
margin: 5px 0px;
border-width: 1px;
border-radius: 10px;
padding: 25px;
color: black;
}
<div class="container">
<div class="content">
<div class="header">Header</div>
<div class="label">
<div>Name</div>
<div>From</div>
<div>To</div>
</div>
<div class="rows">
<div class="row">
<div class="label">
<div>1</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
<div class="row">
<div class="label">
<div>2</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
<div class="row">
<div class="label">
<div>2</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
<div class="row">
<div class="label">
<div>3</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
<div class="row">
<div class="label">
<div>4</div>
<div>1999/01/01</div>
<div>1999/12/01</div>
</div>
</div>
</div>
I go with height calculation .pin-table { height: calc(100vh - 125px); overflow: auto; } but if anyone has better idea feel free to write.

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>

How to have a grid in CSS with columns of different sizes? [duplicate]

I tried to achieve the masonry style using css with the column layout like the markup below.
I want to know if it's possible to make the .green one to take two columns instead of one?
Thank you in advance!
.parent{
column-gap: 1rem;
column-count: 2;
}
.element{
display:inline-block;
background:red;
width:100%;
height:100px;
}
.green{
background:green;
}
<div class="parent">
<div class="element green">
</div>
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
With CSS grid you can use grid-column: span 2:
.wrapper {
display: grid;
grid-gap: 0.5rem;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-flow: dense;
padding: 0.5rem;
}
.box {
background-color: lightblue;
padding: 0.5rem;
}
.a,
.d,
.e,
.f {
background-color: lightcoral;
grid-column: span 2; /* <-- here is the trick */
}
<div class="wrapper">
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<div class="box d">D</div>
<div class="box e">E</div>
<div class="box f">F</div>
<div class="box g">G</div>
<div class="box h">H</div>
</div>
Learn more about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column
Regarding masonry style: At the time of writing, Level 3 of the CSS Grid Layout specification includes a masonry value for grid-template-columns and grid-template-rows layout, though browser support is pretty non-existent: https://caniuse.com/?search=masonry
Learn about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Masonry_Layout
So instead I used grid-auto-flow: dense; on the grid, which makes grid item G come before grid item F. It's not really masonry style (placing elements in optimal position based on available vertical space), but it comes close by making the grid dense filling up all available horizontal space with the next grid item that fits that space.
"dense" packing algorithm attempts to fill in holes earlier in the grid
Learn about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow
Oh, if you are new to CSS grid, I recommend watching Wes Bos' talk “CSS Grid in 45 Minutes!”: https://www.youtube.com/watch?v=DCZdCKjnBCs
CSS Grid layout provides a simple, easy and efficient solution.
.parent {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 100px;
grid-gap: 1rem;
}
.element.green {
grid-column: 1 / -1;
background: green;
}
.element {
background: red;
}
<div class="parent">
<div class="element green"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>
More information:
Make a grid column span the entire row
CSS-only masonry layout
I would say, no you can't make the single .green element take up two columns, becuase you are specifically telling the browser to use two columns. If you need it to span the two columns, then I would suggest using a separate element. Perhaps a more suitable solution for this would be to use the CSS grid layout. The snippet below contains an example of both of these solutions:
.parent {
column-gap: 1rem;
column-count: 2;
}
.element {
display: inline-block;
background: red;
width: 100%;
height: 100px;
}
.green {
background: green;
width: 100%;
height: 100px;
margin-bottom: 1rem;
}
.grid-container {
margin-top: 20px;
display: grid;
grid-template-columns: auto auto;
grid-gap: 1rem;
}
.greenGrid {
background: green;
height: 100px;
grid-column-start: 1;
grid-column-end: 3;
}
.redGrid {
background: red;
height: 100px;
}
<div class="green">
</div>
<div class="parent">
<div class="element">
</div>
<div class="element">
</div>
<div class="element">
</div>
</div>
<div class='grid-container'>
<div class='greenGrid'></div>
<div class='redGrid'></div>
<div class='redGrid'></div>
<div class='redGrid'></div>
</div>

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

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.

CSS Grid responsive layout with auto-fit and minmax for even number of items

What I am trying to accomplish:
There are 4 grid items. At the a widest screen size, I would like the items to be lined up in a row:
item_1 item_2 item_3 item_4
As the screen width shrinks, I would like the items to wrap to the next row like this:
item_1 item_2
item_3 item_4
Then finally at the narrowest, I would like the times to be a single columns
item_1
item_2
item_3
item_4
I found an example which does this but by only wrapping the next item when it can – https://labs.jensimmons.com/2017/03-009.html
Building off of that I tried using nested grid containers based on the example's model:
grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
HTML
.outer_grid {
display:grid;
grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
grid-template-row:1fr 1fr;
grid-gap:1em;
border:5px solid blue;
}
.grid {
display:grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-template-row:1fr 1fr;
grid-gap:1em;
border:5px solid green;
height:200px;
}
.item {
border:2px solid red;
}
<div class="outer_grid">
<div class="grid">
<div class="item">item 1</div>
<div class="item">item 2</div>
</div>
<div class="grid">
<div class="item">item 3</div>
<div class="item">item 4</div>
</div>
</div>
It is nearly working (codepen below) but I'm not sure if this is the right approach or if there is a better way to accomplish this. I have tried using Flexbox too but chose CSS Grid because of the grid-gap feature. Also, I know it can be done but I am trying to do this without media queries.
https://codepen.io/anon/pen/LMqWEr?editors=1100
I tried the below fix for this question and hope it works
https://codepen.io/ronsummer/pen/eYOKRzg
<div class="wrapper">
<div class="box a">A</div>
<div class="box b">B</div>
<div class="box c">C</div>
<div class="box d">D</div>
<div class="box e">E</div>
<div class="box f">F</div>
</div>
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 10px;
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
So from my understanding, you are actually looking for a row of items to be transformed into a column or multiple columns of items when shrinking, without using media queries.
Taking this into consideration, the best approach would be to use Flexbox since it's 1 dimensional.
CSS Grid is also powerful but only when you want to make use of 2-dimensional layout (so both rows & columns).
Also is good to know that Flexbox is content-first opposed to CSS Grid which is layout-first.
Codepen
.flex-container {
display: flex;
width: 100%;
flex-wrap: wrap;
justify-content: center;
}
.flex-container .flex-item {
display: flex;
min-width: 10rem;
width: calc((100% - 1rem * 8 * 2) / 8);
height: 10rem;
padding: 1rem;
margin: 1rem;
align-items: center;
justify-content: center;
background: #1d1d1d;
color: #fff;
font-size: 2rem;
font-weight: 500;
text-align: center;
}
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
<div class="flex-item">8</div>
</div>