Is there a way to collapse certain grid-gaps? - css

I've setup a grid-template but a problem has arisen in the front-end template layer. Basically there comes a time when divs with assigned grid-areas conditionally render onto the page. Being that I have a grid-row-gap declaration in place, it maintains gaps of grid template areas that aren't present on the page. I was wondering if there was a way to collapse these gaps when this sort of thing occurs.
.grid {
display: grid;
grid-template-areas:
'a b'
'a c'
'a d'
'a e'
'a f';
grid-gap: 25px;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
padding: 15px;
border: 1px solid #000;
}
.a {
grid-area: a;
}
.b {
grid-area: b;
}
.c {
grid-area: c;
}
.d {
grid-area: d;
}
.e {
grid-area: e;
}
.f {
grid-area: f;
}
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<!-- <div class="c cell">C</div> -->
<!-- <div class="d cell">D</div> -->
<div class="e cell">E</div>
<div class="f cell">F</div>
</div>

You can think it otherwise, use template and span instead area , and margin instead grid-gap.
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
margin: 1em;
background: #bee;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
padding: 15px;
border: 1px solid #000;
grid-column: 2;
}
.a {
grid-column: 1;
grid-row: 1 / span 10;
/* here what you think is enough */
}
.cell:nth-child(1)~.cell {
margin-left: 24px;
}
.cell:nth-child(2)~.cell {
margin-top: 24px;
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<div class="c cell">C</div>
<div class="d cell">D</div>
<div class="e cell">E</div>
<div class="f cell">F</div>
</div>
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<div class="d cell">D</div>
<div class="f cell">F</div>
</div>

Don't use template-areas and reply on auto placement:
.grid {
display: grid;
grid-template-columns: 1fr 1fr; /* 2 columns */
column-gap: 25px;
margin:5px;
}
.cell {
display: flex;
align-items: center;
justify-content: center;
padding: 15px;
border: 1px solid #000;
}
.grid .a {
grid-row: span 5; /* take 5 rows */
}
/* to replace vertical gap, don't apply to "a" and last-child */
.cell:not(.a):not(:last-child) {
margin-bottom:25px;
}
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<!-- <div class="c cell">C</div> -->
<!-- <div class="d cell">D</div> -->
<div class="e cell">E</div>
<div class="f cell">F</div>
</div>
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<div class="c cell">C</div>
<!-- <div class="d cell">D</div> -->
<div class="e cell">E</div>
<div class="f cell">F</div>
</div>
<div class="grid">
<div class="a cell">A</div>
<div class="b cell">B</div>
<div class="c cell">C</div>
</div>

Related

Make Grid Item Auto Fill

sorry I'm very new to grid-layout
I have a layout that I believe it is really easy for grid system
but I have no idea how to modify it for my layout:
the layout has three type:
if only one item: full width, full height
if two items, left and right; 50% width, full height
if three items, correct code is below
.container {
display: grid;
width: 200px;
height: 200px;
grid-template-columns: 1fr 1fr;
grid-template-rows: 50% 50%;
grid-gap: 8px;
}
.a {
grid-column: 1;
grid-row: 1 / 3;
background: red;
}
.b {
grid-column: 2;
grid-row: 1;
background: blue;
}
.c {
grid-column: 2;
grid-row: 2;
background: green;
}
<div class="container">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
</div>
code above is for type 3 and is really correct
how should I modify it let it fit type 1 and 2 ??
You can do it like below:
.container {
display: inline-grid;
margin:5px;
vertical-align:top;
width: 200px;
height: 200px;
grid-gap: 8px;
}
.a { background: red;}
.b { background: blue;}
.c { background: green;}
/* when 2 items we add another column*/
.container :nth-child(2):nth-last-child(1) {
grid-column:2;
}
/* when 3 items we add another row as well */
.container :nth-child(3):nth-last-child(1) {
grid-row:2;
grid-column:2;
}
/* when 3 items, the first one will span 2 rows*/
.container :first-child:nth-last-child(3) {
grid-row:span 2;
}
<div class="container">
<div class="a"></div>
</div>
<div class="container">
<div class="b"></div>
</div>
<div class="container">
<div class="c"></div>
</div>
<div class="container">
<div class="a"></div>
<div class="b"></div>
</div>
<div class="container">
<div class="b"></div>
<div class="c"></div>
</div>
<div class="container">
<div class="a"></div>
<div class="c"></div>
</div>
<div class="container">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
</div>

How to set equal width for flex elements?

Why blocks .b have different width? How to set it equal?
.parent {
display: flex;
}
.parent>div {
flex: 1 1 auto;
}
.parent .b {
display: flex;
}
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div>
Why blocks <div class="cell"> have different width?
Edit: use CSS grid and auto-fit:
.parent {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.parent {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
.parent>div {
background-color: lightblue;
margin-left: 5px;
}
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
<div class="cell">>
<div class="b"></div>
</div>
</div>
Second re-edit**
First choice you can do is just set a flex on the parent element as this will only effect the first element below that, which in this case is the cell class, i will add a border on the cell class so you can see this in effect
<div class="parent">
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div class="cell">
<div class="b"></div>
</div>
<div>
.parent {
display: flex;
width: 70%;
}
.cell {
width: 20%;
height: 100px;
border: 1px solid orange;
}
here you can set the size of your parent width which will be the size across your screen, you can then set the width of the .cell childs and they will all then be the same, but only at a maximum of the parent
** second option you can do
Here is a simpler version, and i have added 3 different classes to show how you can choose the sizing you want
<div class="parent">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div>
.parent {
display: flex;
width: 80%;
height: 100px;
}
.a {
flex: 40%;
border: 1px solid greenyellow;
}
.b {
flex: 20%;
border: 1px solid orange;
}
.c {
flex: 20%;
border: 1px solid blue;
}
Of course you can change them back and have them all be called the same class, and just assign one width and again they will all be the same... i hope this helps
I think they all are in same width. You need to use this css instead of the .parent>div selector
.cell {
flex: 1 1 auto;
}
.parent {
display: flex;
}
.cell {
flex: 1 1 auto;
}
.parent .b {
display: flex;
align-items: center;
justify-content: center;
}
.b {
height: 50px;
}
.cell:nth-child(1) {
background: red;
}
.cell:nth-child(2) {
background: yellow;
}
.cell:nth-child(3) {
background: green;
}
.cell:nth-child(4) {
background: teal;
}
<div class="parent">
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div class="cell">
<div class="b">hi</div>
</div>
<div>

How do I remove grid gaps when columns are not present?

I have a section of html that needs to be displayed in a certain way but some elements may be optional and I'm not sure if I can do it with display:grid.
I need to have 3 columns, but the first and last one are optional and I need to remove the gap when they are not present.
Note that the markup needs to be this one without extra wrapper :
.grid {
display: grid;
grid-template-columns: auto 1fr auto;
grid-gap: 0 20px;
align-items: center;
background-color: lightgrey;
}
.grid > .image {
grid-column: 1;
grid-row: 1 / span 2;
background-color: red;
}
.grid > .title {
grid-column: 2;
background-color: blue;
}
.grid > .description {
grid-column: 2;
background-color: purple;
}
.grid > .button {
grid-column: 3;
grid-row: 1 / span 2;
background-color: green;
}
<div class="grid">
<div class="image">image</div>
<div class="title">title</div>
<div class="description">description</div>
<div class="button">button</div>
</div>
<p> </p>
<p>Unwanted gap when no image :</p>
<div class="grid">
<div class="title">title</div>
<div class="description">description</div>
<div class="button">button</div>
</div>
<p> </p>
<p>Unwanted gap when no image or button :</p>
<div class="grid">
<div class="title">title</div>
<div class="description">description</div>
</div>
Rely on implicit column creation and keep only one explicit column
.grid {
display: grid;
grid-template-columns: 1fr; /* one column here */
grid-gap: 0 20px;
align-items: center;
background-color: lightgrey;
}
.grid > .image {
grid-column: -3; /* this will create an implicit column at the start */
grid-row: span 2;
background-color: red;
}
.grid > .title {
background-color: blue;
}
.grid > .description {
background-color: purple;
}
.grid > .button {
grid-column: 2; /* this will create an implicit column at the end */
grid-row:1/ span 2;
background-color: green;
}
<div class="grid">
<div class="image">image</div>
<div class="title">title</div>
<div class="description">description</div>
<div class="button">button</div>
</div>
<p> </p>
<div class="grid">
<div class="title">title</div>
<div class="description">description</div>
<div class="button">button</div>
</div>
<p> </p>
<div class="grid">
<div class="image">image</div>
<div class="title">title</div>
<div class="description">description</div>
</div>
<p> </p>
<div class="grid">
<div class="title">title</div>
<div class="description">description</div>
</div>
Instead of using grid gaps, use margins on the individual elements.
.grid {
display: grid;
grid-auto-columns: auto 1fr auto;
/* grid-gap: 0 20px; */
align-items: center;
background-color: lightgrey;
}
.grid > .image {
margin-right: 20px; /* new */
grid-column: 1;
grid-row: 1 / span 2;
background-color: red;
}
.grid > .button {
margin-left: 20px; /* new */
grid-column: 3;
grid-row: 1 / span 2;
background-color: green;
}
.grid > .title {
grid-column: 2;
background-color: blue;
}
.grid > .description {
grid-column: 2;
background-color: purple;
}
<div class="grid">
<div class="image">image</div>
<div class="title">title</div>
<div class="description">description</div>
<div class="button">button</div>
</div>
<p> </p>
<p>NO unwanted gap when no image :</p>
<div class="grid">
<div class="title">title</div>
<div class="description">description</div>
<div class="button">button</div>
</div>
<p> </p>
<p>NO unwanted gap when no image or button :</p>
<div class="grid">
<div class="title">title</div>
<div class="description">description</div>
</div>

CSS Grid auto-fit column automatically wraps

from the example I have three columns, when resized at a certain view-port it will wrap onto the next row, how can I target that individual div and make it fill the available width?
.boxes {
color: white;
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.box {
background-color: blue;
padding: 10px;
}
<section class = "boxes">
<div class="box">
<p>Box 1</p>
</div>
<div class="box">
<p>Box 2</p>
</div>
<div class="box">
<p>Box 3</p>
</div>
</section>
Codepen:
CodePen
You need flexbox for this:
body {
color: white;
}
.boxes {
display: flex;
flex-wrap: wrap;
}
.box {
background-color: blue;
padding: 10px;
min-width: 250px;
box-sizing:border-box;
margin: 10px;
flex-grow: 1;
}
<section class="boxes">
<div class="box">
<p>Box 1</p>
</div>
<div class="box">
<p>Box 2</p>
</div>
<div class="box">
<p>Box 3</p>
</div>
</section>
Limit columns by max-width
you can stay with grid, but it look good only if you stay with 2 columns.
for more columns its more complicated and you can define what you want, to use grid or to use flex for convenient way.
html {
box-sizing: border-box;
}
body {
background-color: white;
color: white;
}
.boxes {
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
max-width: 700px;
margin: 0 auto;
text-align: center;
}
.box {
background-color: blue;
padding: 10px;
}
.box:last-child:nth-child(odd) {
grid-column: 1/3;
}
<!DOCTYPE html>
<html>
<head>
<title>Column Resize</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<section class="boxes">
<div class="box">
<p>Box 1</p>
</div>
<div class="box">
<p>Box 2</p>
</div>
<div class="box">
<p>Box 3</p>
</div>
</section>
</body>
</html>

CSS Grid: dynamically span the last column

Is it possible to automatically span the last column to occupy the remaining space in the grid? Basically I'm trying to achieve this:
.row {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.col {
background: blue;
padding: 20px;
border: 1px solid red;
}
.col:last-child {
background: yellow;
/* missing magic here */
}
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
<div class="row">
<div class="col"></div>
<div class="col"></div>
</div>
<div class="row">
<div class="col"></div>
</div>
Unfortunately, it seems that in current version of CSS grid there is no true magic like grid-column: span auto / -1 as a universal solution. But for this particular case of 3x1 grid you can do something like the following:
.row {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.col {
background: blue;
padding: 20px;
border: 1px solid red;
}
.col:last-child {
background: yellow;
grid-column-end: -1;
}
.col:nth-child(1):last-child {
grid-column-start: 1;
}
.col:nth-child(2):last-child {
grid-column-start: 2;
}
<div class="row">
<div class="col"></div>
<div class="col"></div>
<div class="col"></div>
</div>
<div class="row">
<div class="col"></div>
<div class="col"></div>
</div>
<div class="row">
<div class="col"></div>
</div>

Resources