grid-column-end: -1; weird behavior - html

What I intend to achieve is something that looks as follows:
Where the header spans the full width of the container, where there can be 3 or 4 columns having the same width in the second row, and where the footer has the same width as the first column.
I thought I could achieve this with the following HTML and CSS code, but no. grid-column-end is giving me headaches. If I set it to 5, it looks as I want in the case that there are four items in the second row, but not if there are only 3, in which case grid-column-end should be 4. Hence, the solution of using -1, which refers to the last grid-line, but then a grid containing something like 40 columns is created.
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(10px, 1fr));
grid-template-rows: auto minmax(0, 1fr) auto;
grid-gap: 10px;
width: 100%;
}
.header {
grid-column-start: 1;
grid-column-end: -1;
grid-row: 1;
background-color: #bbb;
padding: 20px;
}
.item {
background-color: #ddd;
border: 1px solid #aaa;
padding: 20px;
grid-row: 2;
}
.footer {
grid-column: 1 / 2;
grid-row: 3;
background-color: #bbb;
padding: 20px;
}
<div class="container">
<div class="header">Header</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="footer">Footer</div>
</div>

Related

How to use CSS Grid to make layout where one column has a maximum size

I'm trying to make a layout with a "page".
I would have 3 columns, 1st and 3th would use only 10% of the space, and the middle 80%. Until there no problem. But I would like that as soon as the middle part reach 64rem, it's only the first and last column that grow.
Currently I've tried this:
.container {
display: grid;
grid-template-columns: 10% minmax(80%, 64rem) 10%;
grid-template-rows: min-content auto;
min-height: 100vh;
background-color: red;
}
.header {
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
background-color: blue;
}
.content {
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 3;
background-color: yellow;
}
<div class="container">
<div class="header">
header
</div>
<div class="content">
content
</div>
</div>
But it doesn't stops at 64rem. Any idea how to adress this issue?
Replace the 10% with 1fr and consider min() instead of minmax(). I used 32rem instead of 64rem to easily demonstrate the trick
.container {
display: grid;
grid-template-columns: 1fr min(80%, 32rem) 1fr;
grid-template-rows: min-content auto;
min-height: 100vh;
background-color: red;
}
.header {
grid-column: 2;
background-color: blue;
}
.content {
grid-column: 2;
background-color: yellow;
}
<div class="container">
<div class="header">
header
</div>
<div class="content">
content
</div>
</div>
You can also use padding and simplify the code like below:
.container {
display: grid;
padding-inline: max(10%,(100% - 32rem)/2);
grid-template-rows: min-content 1fr;
min-height: 100vh;
background-color: red;
}
.header {
background-color: blue;
}
.content {
background-color: yellow;
}
<div class="container">
<div class="header">
header
</div>
<div class="content">
content
</div>
</div>
You need to think otherwise and set width and max-width on the container itself. your template becomes then : 1fr auto 1fr , wher both sides will grow as much as the middle column will allow them to.
Example below
.container {
display: grid;
grid-template-columns: 1fr auto 1fr;
grid-template-rows: min-content auto;
min-height: 100vh;
background-color: red;
}
.header {
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
background-color: blue;
}
.content {
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 3;
background-color: yellow;
width:80vw;/* where the parent container fills the whole screen's width */
max-width:64rem;
}
<div class="container">
<div class="header">
header
</div>
<div class="content">
content
</div>
</div>

Grid items expand to follow offset between columns [duplicate]

This question already has answers here:
CSS-only masonry layout
(4 answers)
Closed 1 year ago.
I'm trying to make an html/css card system that automatically places itself on a css grid. This css grid is divided into two columns. In the left column, a div adds an offset to the rest of the column, and has no fixed size. I want to keep this offset between the two columns.
The problem is that the first card on the left (number 2) grows to compensate for the offset, but all cards must have the same size. How can I fix that without fixing the size of each card ?
What I would like to do:
What I currently have:
A simple example of code to reproduce it:
.grid {
display: grid;
background-color: #eee;
grid-gap: 5px 5px;
grid-template-columns: repeat(2, 1fr);
grid-auto-flow: dense;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 60px;
font-size: 150%;
}
.grid__1 {
background-color: #ccc;
grid-column: 1 / 2;
padding: 5px;
font-size: 1rem;
}
.grid__item {
grid-column: span 1;
grid-row: span 2;
}
<div class="grid">
<div class="box grid__1">head</div>
<div class="box grid__item">1</div>
<div class="box grid__item">2</div>
<div class="box grid__item">3</div>
<div class="box grid__item">4</div>
<div class="box grid__item">5</div>
<div class="box grid__item">6</div>
</div>
I made a live example here : https://jsfiddle.net/rLpqt75d/3/
I did some research and it looks like you are trying to replicate a mansonry-layout.
If you don't know what it is, it is the layout used by pintarest.
After a while googleing I found a great article you could look into:
https://kulturbanause.de/blog/responsive-masonry-layout-mit-css/
I'll try to summarize:
In the future we will get a css property: grid-template-rows: masonry;
But until then we will have to stick to flex-box.
I copied the example of the blog post to a fiddle and modified it a little for a better overview:
https://jsfiddle.net/8k1nyg39/41/
Hope I could help someone (:
EDIT:
So I experimented a bit with it and it seems like you need a predetermined height for your container...
If you need your container to change height dynamically the only remaining workaround I know of would be a js library like Magic Grid ...
define a pair of rows for the property grid-auto-rows, this will set the correct size :
.grid {
display: grid;
background-color: #eee;
grid-gap: 5px 5px;
grid-template-columns: repeat(2, 1fr);
grid-auto-flow: dense;
grid-auto-rows: 40px 200px; /* added */
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 60px;
font-size: 150%;
}
.grid__1 {
background-color: #ccc;
grid-column: 1 / 2;
padding: 5px;
font-size: 1rem;
}
.grid__item {
grid-column: span 1;
grid-row: span 2;
}
<div class="grid">
<div class="box grid__1">head</div>
<div class="box grid__item">1</div>
<div class="box grid__item">2</div>
<div class="box grid__item">3</div>
<div class="box grid__item">4</div>
<div class="box grid__item">5</div>
<div class="box grid__item">6</div>
</div>
/* height is your var */
.grid {
display: grid;
background-color: #eee;
grid-gap: 5px 5px;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: 40px 1fr;
height: 100vh;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 60px;
font-size: 150%;
}
.grid__head {
background-color: #ccc;
grid-column: 1 / 2;
padding: 15px;
font-size: 1rem;
}
.grid__item {
grid-column: span 1;
grid-row: span 2;
}
<div class="grid">
<div class="box grid__head">head</div>
<div class="box grid__item">1</div>
<div class="box grid__item">2</div>
<div class="box grid__item">3</div>
<div class="box grid__item">4</div>
<div class="box grid__item">5</div>
<div class="box grid__item">6</div>
</div>
enter link description here
Switch from grid-row: span 2 to span 3 (or 4) on .grid__item.
.grid {
display: grid;
background-color: #eee;
grid-gap: 5px 5px;
grid-template-columns: repeat(2, 1fr);
grid-auto-flow: dense;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 60px;
font-size: 150%;
}
.grid__1 {
background-color: #ccc;
grid-column: 1 / 2;
padding: 5px;
font-size: 1rem;
}
.grid__item {
grid-column: span 1;
grid-row: span 3; /* ADJUSTMENT */
}
<div class="grid">
<div class="box grid__1">head</div>
<div class="box grid__item">1</div>
<div class="box grid__item">2</div>
<div class="box grid__item">3</div>
<div class="box grid__item">4</div>
<div class="box grid__item">5</div>
<div class="box grid__item">6</div>
</div>
The problem is that the first card on the left (number 2) grows to compensate for the offset, but all cards must have the same size.
If you switch from having the items span two rows (grid-row: span 2) to instead span three (grid-row: span 3), or four, the items can better absorb the offset height.
2 rows (original layout) — notice how the rows are laid out
3 rows (revised layout)
This may also be an alternative: CSS-only masonry layout

CSS layout - grid or flex [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I'm trying to create this layout.
https://pasteboard.co/K1C5o3k.jpg
I tried to use display: grid but the spacing was strange. What would be the best solution? Use grid or flexbox? How do I achieve this spacing using grid or flexbox?
<div class="wrap">
<div class="test-grid">
<div class="card box1">some text</div>
<div class="card box2">some text</div>
<div class="card">some text</div>
<div class="card box4">some text</div>
</div>
</div>
.wrap {
max-width: 600px;
}
.test-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 1em;
}
.card {
background-color: tomato;
width: 160px;
min-height: 220px;
}
.box1 {
margin-top: 40px;
}
.box4 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 2;
grid-row-end: 3;
}
On your grid layout, I use grid-template-row/columns to define the fraction amount and then grid-template-areas to layout the elements, for each child element you want to define the unique class as its grid-area. You can use gap to control the spacing between the elements. Once you define a height and width for the parent element, the children will fill in their respective fraction, along with any defined gap.
Then use a media query with flex for your mobile layout. You may need to tweek the CSS a bit to get it to look just as you want, but the following example should do the trick.
.test-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
gap: 20px 20px;
grid-template-areas:
". two ."
"one two four"
"one three four"
". three .";
width: 100vw;
height: 100vh;
}
.one {
grid-area: one;
background-color: tomato;
}
.two {
grid-area: two;
background-color: tomato;
}
.three {
grid-area: three;
background-color: tomato;
}
.four {
grid-area: four;
background-color: tomato;
}
.box {
display: flex;
justify-content: center;
align-items: center;
}
#media only screen and (max-width: 600px) {
.test-grid {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.box {
width: 100%;
height: 100%;
}
}
<div class="test-grid">
<div class="one box">some text</div>
<div class="two box">some text</div>
<div class="three box">some text</div>
<div class="four box">some text</div>
</div>
Both Grid and flex will do the work, it just based on your preferences.
Snippet below will do the trick and when the screen became small (less than 500px). The grid will show as a list.
.wrap {
max-width: 600px;
}
.test-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 1em;
}
.card {
background-color: tomato;
width: 160px;
min-height: 220px;
}
.box1 {
grid-column: 1/span 1;
grid-row: 2/span 2;
}
.box2 {
grid-column: 2/span 2;
grid-row: 1/span 1;
}
.box3 {
grid-column: 3/span 2;
grid-row: 2/span 2;
}
.box4 {
grid-column: 2/span 2;
grid-row: 3/span 3;
}
#media (max-width: 500px) {
.test-grid {
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
<div class="wrap">
<div class="container">
<div class="test-grid">
<div class="card box1">box1</div>
<div class="card box2">box2</div>
<div class="card box3">box3</div>
<div class="card box4">box4</div>
</div>
</div>
Here's an option using only grid. In this example we create many small grid rows (10px each) which then allows you to start each element at a specific row and adjust the boxes by 10 pixel increments.
.test-grid {
display: grid;
grid-template-columns: repeat(3, 160px);
grid-template-rows: repeat(45, 10px);
column-gap: 10px;
}
.card {
background-color: tomato;
width: 160px;
min-height: 220px;
}
.box1 {
grid-row-start: 10;
}
.box2 {
grid-row-start: 0;
grid-column-start: 2;
}
.box3 {
grid-row-start: 24;
grid-column-start: 2;
}
.box4 {
grid-row-start: 8;
grid-column-start: 3;
}
<div class="wrap">
<div class="test-grid">
<div class="card box1">some text</div>
<div class="card box2">some text</div>
<div class="card box3">some text</div>
<div class="card box4">some text</div>
</div>
</div>

Filling large gaps between rows

In the code box-2 and box-3 row height auto stretches to box-1 height which is tallest item in the row. There is a extra gap in box-2 and box-3 columns. I want that gap to be filled up by the box-5 which is in the second row. Fiddle
.container {
display: grid;
grid-template-columns: 20% 40% 40%;
grid-gap: 20px;
}
.container > div {
border: 1px solid red;
}
.box-1 {
background-color: lightgreen;
height: 300px;
}
.box-2 {
background-color: lightsalmon;
height: 150px;
}
.box-3 {
background-color: lightsalmon;
height: 150px;
}
.box-4 {
background-color: lightskyblue;
height: 500px;
}
.box-5 {
background-color: lightseagreen;
grid-column: 2/-1;
}
<div class="container">
<div class="box-1"></div>
<div class="box-2"></div>
<div class="box-3"></div>
<div class="box-4"></div>
<div class="box-5"></div>
</div>
This is the output I am looking for
You're setting the height of the grid items directly, and not defining any rows on the grid container. Therefore, the grid algorithm has to create rows to accommodate the grid areas. It only needs to create two rows to complete the layout. That's why there's a large gap beneath boxes 2 and 3. Box 1, being the tallest, sets the height of top row.
The layout you want requires at least three rows.
Try this approach: Set the rows (and heights) at the container level, then set the grid areas.
.container {
display: grid;
grid-template-columns: 1fr 2fr 2fr;
grid-template-rows: repeat(3, 150px);
grid-gap: 10px;
}
.box-1 {
grid-column: 1;
grid-row: 1 / span 2;
background-color: lightgreen;
}
.box-2 {
grid-column: 2;
grid-row: 1;
background-color: lightsalmon;
}
.box-3 {
grid-column: 3;
grid-row: 1;
background-color: lightsalmon;
}
.box-4 {
grid-column: 2 / -1;
grid-row: 2 / 4;
background-color: lightskyblue;
}
.box-5 {
grid-column: 1;
grid-row: 3;
background-color: lightseagreen;
}
<div class="container">
<div class="box-1">1</div>
<div class="box-2">2</div>
<div class="box-3">3</div>
<div class="box-4">4</div>
<div class="box-5">5</div>
</div>
If you want more options for sizing grid areas, then increase the number of rows / columns.
For example, instead of this:
grid-template-rows: repeat(3, 150px)
...you can do this:
grid-template-rows: repeat(9, 50px)
... then span grid areas across rows as needed.
Keep box 1 and box 3 in one div align it vertically and keep all other 3 boxes in one container in 1 container then u can do this easily

Making grid responsive

Any idea of how to make this grid responsive?
This is my CSS:
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 100px 100px 100px;
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.a {
grid-column: 1 / 3;
grid-row: 1;
}
.b {
grid-column: 3 ;
grid-row: 1 / 3;
}
.c {
grid-column: 1 ;
grid-row: 2 ;
}
.d {
grid-column: 2;
grid-row: 2;
}
HTML
<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>
I tried this code:
#media only screen and (max-width:500px) {
.box {
width: 100%;
margin-right: 0;
float: none;
margin-bottom: 20px !important;
}
What's the best way to accomplish this?
I agree with #Petra that you need to use fr, but use a media query if you want to display them stacked on a mobile device. You could also just change the display to block. Make sure you add these after the initial CSS so that it isn't overridden.
#media screen and (max-width: 512px) {
.wrapper {
grid-template-columns: 1fr;
}
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr 1fr;
background-color: #fff;
color: #444;
}
ith CSS Grid Layout, we get a new flexible unit: the Fr unit. Fr is a fractional unit and 1fr is for 1 part of the available space.