How to collapse vertical space around grid items? - css

With a screen size > 576px and without changing the HTML, how can I collapse the divs so that the divs in the right-hand column appear below each other with only a 10px grid-row-gap.
The description, features and tick-features divs all have dynamic content.
.container {
display: grid;
grid-row-gap: 10px;
background: lightgray;
font-family: sans-serif;
padding: 0;
}
.container h1, .container div {
color: white;
padding: 10px;
margin: 0;
}
.container h1 {
background: blue;
}
.container .description {
background: darkslategray;
}
.container .features {
background: green;
}
.container .tick-features {
background: purple;
}
.container .static-map {
background: maroon;
}
.container .full-width {
background: darkolivegreen;
}
#media screen and (min-width: 576px) {
.container {
grid-template-columns: 50% 1fr;
grid-template-rows: auto;
grid-column-gap: 10px;
max-width: 700px;
}
.container h1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.container .description {
grid-column: 1/2;
grid-row: 2/5;
height: 500px;
}
.container .features {
grid-column: 2 /3;
grid-row: 2 / 3;
height: 100px;
}
.container .tick-features {
grid-column: 2 /3;
grid-row: 3 / 4;
height: 100px;
}
.container .static-map {
grid-column: 2 /3;
grid-row: 4 / 5;
}
.container .full-width {
grid-column: 1 / 3;
grid-row: 5 / 6;
}
}
<div class="container">
<h1>HEADER</h1>
<div class="features">Features</div>
<div class="description">Description</div>
<div class="tick-features">Tick features</div>
<div class="static-map">Static Map</div>
<div class="full-width">Full width div</div>
</div>
Adding images to show what I'm trying to achieve.
+++

The Problem
It's important to note that the cells in the right-hand column are already next to each other, separated only by the 10px row gap.
As you can see with the dashed outlines, there is no wide vertical gap between the cells on the right. The are right next to each other.
The problem is that each item within the cell has a lower height than the row it's in.
.container .features {
grid-column: 2 /3;
grid-row: 2 / 3;
height: 100px;
}
.container .tick-features {
grid-column: 2 /3;
grid-row: 3 / 4;
height: 100px;
}
With each item set to height: 100px, it doesn't cover the full height of the cell, leaving a lot of empty space.
Solutions
Depending on what exactly you need, you can approach the problem in various ways. Here are two:
1. Use min-height instead of height
Replace height: 100px with min-height: 100px, allowing the items to consume all free space. (Consider a similar switch for the .description item.)
.container {
display: grid;
grid-row-gap: 10px;
background: lightgray;
font-family: sans-serif;
padding: 0;
}
.container h1,
.container div {
color: white;
padding: 10px;
margin: 0;
}
.container h1 {
background: blue;
}
.container .description {
background: darkslategray;
}
.container .features {
background: green;
}
.container .tick-features {
background: purple;
}
.container .static-map {
background: maroon;
}
.container .full-width {
background: darkolivegreen;
}
#media screen and (min-width: 576px) {
.container {
grid-template-columns: 50% 1fr;
grid-template-rows: auto;
grid-column-gap: 10px;
max-width: 700px;
}
.container h1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.container .description {
grid-column: 1/2;
grid-row: 2/5;
/* height: 500px; */
min-height: 500px; /* new */
}
.container .features {
grid-column: 2 /3;
grid-row: 2 / 3;
/* height: 100px; */
min-height: 100px; /* new */
}
.container .tick-features {
grid-column: 2 /3;
grid-row: 3 / 4;
/* height: 100px; */
min-height: 100px; /* new */
}
.container .static-map {
grid-column: 2 /3;
grid-row: 4 / 5;
}
.container .full-width {
grid-column: 1 / 3;
grid-row: 5 / 6;
}
}
<div class="container">
<h1>HEADER</h1>
<div class="features">Features</div>
<div class="description">Description</div>
<div class="tick-features">Tick features</div>
<div class="static-map">Static Map</div>
<div class="full-width">Full width div</div>
</div>
2. Use grid-template-rows
You may also be able to handle the problem at the container level, using grid-template-rows.
.container {
display: grid;
grid-row-gap: 10px;
background: lightgray;
font-family: sans-serif;
padding: 0;
}
.container h1,
.container div {
color: white;
padding: 10px;
margin: 0;
}
.container h1 {
background: blue;
}
.container .description {
background: darkslategray;
}
.container .features {
background: green;
}
.container .tick-features {
background: purple;
}
.container .static-map {
background: maroon;
}
.container .full-width {
background: darkolivegreen;
}
#media screen and (min-width: 576px) {
.container {
grid-template-columns: 50% 1fr;
grid-template-rows: 50px minmax(100px, 1fr) minmax(100px, 1fr) 100px 50px;
grid-column-gap: 10px;
max-width: 700px;
}
.container h1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
.container .description {
grid-column: 1/2;
grid-row: 2/5;
/* height: 500px; */
}
.container .features {
grid-column: 2 /3;
grid-row: 2 / 3;
/* height: 100px */
}
.container .tick-features {
grid-column: 2 /3;
grid-row: 3 / 4;
/* height: 100px; */
}
.container .static-map {
grid-column: 2 /3;
grid-row: 4 / 5;
}
.container .full-width {
grid-column: 1 / 3;
grid-row: 5 / 6;
}
}
<div class="container">
<h1>HEADER</h1>
<div class="features">Features</div>
<div class="description">Description</div>
<div class="tick-features">Tick features</div>
<div class="static-map">Static Map</div>
<div class="full-width">Full width div</div>
</div>

Related

Grid Layout not changing when changing screen size, Media Queries CSS

I'm trying to get elements from being in 2 columns to 1 when changing to a smaller screen size using display:grid and Media Query. Furthermore, despite using fr units it doesn't get smaller with the screen size after certain value and it shows horizontal scrolling which I dont want. But I cannot understand why it doesn't work, have already spent several hours looking for helpful information.
*{max-width:100%;}
#grid {
display: grid;
height: 200px;
grid-template-columns: 1fr 1fr 1fr;
}
#item1 {
grid-column:2;
background-color: lime;
}
#item2 {
grid-column:2;
background-color: yellow;
grid-row: 2;
}
#item3 {
grid-column:2;
background-color: blue;
grid-row: 3;
}
#item4 {
grid-column:2;
background-color: green;
grid-row: 4;
}
#media all and(min-width:500px){
#grid {
height: 200px;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
}
#item1 {
grid-column:2;
}
#item2 {
grid-column:4;
grid-row:1;
}
#item3 {
grid-column:2;
grid-row: 3;
}
#item4 {
grid-column:4;
grid-row: 3;
}
}
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
<div id="item4"></div>
</div>
Your issue is a simple space between the parenthesis containing the min-width size and the and -> #media all and (min-width: 500px) instead of #media all and(min-width: 500px)
*{max-width:100%;}
#grid {
display: grid;
height: 200px;
grid-template-columns: 1fr 1fr 1fr;
}
#item1 {
grid-column:2;
background-color: lime;
}
#item2 {
grid-column:2;
background-color: yellow;
grid-row: 2;
}
#item3 {
grid-column:2;
background-color: blue;
grid-row: 3;
}
#media all and (min-width: 500px){
#grid {
height: 200px;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
}
#item1 {
grid-column:2;
background-color: lime;
}
#item2 {
grid-column:4;
background-color: yellow;
grid-row:1;
}
#item3 {
grid-column:2;
background-color: blue;
grid-row: 3;
}
#item4 {
grid-column:4;
background-color: blue;
grid-row: 3;
}
}
<div id="grid">
<div id="item1"></div>
<div id="item2"></div>
<div id="item3"></div>
<div id="item4"></div>
</div>
I can't completely understand why, but assigning these properties to the meta tag solved the problem: name="viewport" content="width=device-width, initial-scale=1.0"
More info: The Viewport
So here is why: Explanation

Element not spanning explicit and implicit columns

In a grid container with 1 column and 1 row, If I have an implicit column on the 1st row, how do I get an element in the second row (the green column in the example) to span both the explicit and implicit columns? Thanks in advance
*{
margin: 0;
padding: 0;
color: white;
padding: 0.6em
}
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 2fr;
grid-auto-columns: auto;
}
button {
background-color: red;
grid-row-start: 1;
grid-column-start: 2;
grid-column-end: 3;
}
header {
background-color: blue;
grid-row-start: 1;
}
p {
background-color: green;
grid-column-start: 1;
grid-column-end: -1;
width: 100%;
}
<div class="grid">
<header>title</header>
<button>button</button>
<p>paragraph</p>
</div>
*{
margin: 0;
padding: 0;
color: white;
padding: 0.6em
}
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 2fr;
grid-auto-columns: auto;
}
button {
background-color: red;
grid-row-start: 1;
grid-column-start: 2;
grid-column-end: 3;
}
header {
background-color: blue;
grid-row-start: 1;
}
p {
background-color: green;
grid-column-start: 1;
grid-column-end: 3; /*This is what changed*/
}
<div class="grid">
<header>title</header>
<button>button</button>
<p>paragraph</p>
</div>
Since the implicit column is an auto one, you can make explicit and simplify your code like below
* {
padding: 0.6em
}
.grid {
display: grid;
grid-template-columns: 1fr auto;
grid-template-rows: 2fr;
color: white;
}
button {
background-color: red;
}
header {
background-color: blue;
}
p {
background-color: green;
grid-column: 1/-1;
}
<div class="grid">
<header>title</header>
<button>button</button>
<p>paragraph</p>
</div>
<div class="grid">
<header>title</header>
<p>paragraph</p>
</div>

CSS Grid gutter is causing columns to overflow, how do I force the column width to conform

I'm trying to create a fairly simple 12 column CSS Grid framework and allow the nesting of grids.
.grid {
grid-template-columns: repeat($grid-column-count, minmax(0, 1fr));
column-gap: 2rem;
}
I'm currently having an issue where the fractional columns are being pushed out of the nested grid container when increasing the gutter width, no matter what content is in it.
I've tried setting the minmax value to 0 when declaring the columns but it still insists on expanding. I know this is because the width of the gutters adds up to more than the content, but is there a way to force it down without using the overflow property?
Columns are being pushed by the gutter and/or content:
...when columns should accommodate gutter instead:
Codepen
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
.container {
display: grid;
grid-template-columns: [left-gutter-start] auto [left-gutter-end] minmax(0, 960px) [main-content-end] auto [right-gutter-end];
overflow-wrap: break-word;
}
.container>.grid {
grid-column-start: left-gutter-end;
grid-column-end: main-content-end;
}
.container>.grid.grid-breakout {
grid-column-start: left-gutter-start;
grid-column-end: right-gutter-end;
}
.grid {
width: 100%;
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
-webkit-column-gap: 2rem;
column-gap: 2rem;
grid-column-end: span 12;
}
.grid .grid {
-webkit-column-gap: 2rem;
column-gap: 2rem;
}
.grid .col-1 {
grid-column-end: span 1;
}
.grid .col-2 {
grid-column-end: span 2;
}
.grid .col-3 {
grid-column-end: span 3;
}
.grid .col-4 {
grid-column-end: span 4;
}
.grid .col-5 {
grid-column-end: span 5;
}
.grid .col-6 {
grid-column-end: span 6;
}
.grid .col-7 {
grid-column-end: span 7;
}
.grid .col-8 {
grid-column-end: span 8;
}
.grid .col-9 {
grid-column-end: span 9;
}
.grid .col-10 {
grid-column-end: span 10;
}
.grid .col-11 {
grid-column-end: span 11;
}
.grid .col-12 {
grid-column-end: span 12;
}
.grid .col-end {
grid-column-end: -1;
}
.grid .colstart-start {
grid-column-start: 1;
}
.grid .colstart-2 {
grid-column-start: 3;
}
.grid .colstart-3 {
grid-column-start: 4;
}
.grid .colstart-4 {
grid-column-start: 5;
}
.grid .colstart-5 {
grid-column-start: 6;
}
.grid .colstart-6 {
grid-column-start: 7;
}
.grid .colstart-7 {
grid-column-start: 8;
}
.grid .colstart-8 {
grid-column-start: 9;
}
.grid .colstart-9 {
grid-column-start: 10;
}
.grid .colstart-10 {
grid-column-start: 11;
}
div[class*="col-"] {
text-align: left;
background-color: orange;
font-size: 12px;
font-family: sans-serif;
}
div[class*="col-"]:before {
content: attr(class);
display: inline-block;
margin: 4px;
}
.container[class*="col-"]:before {
display: none;
}
div[class*="col-"] div[class*="col-"] {
background: lightgreen;
}
div[class*="col-"] div[class*="col-"]:after {
content: " (nested)";
display: inline-block;
margin: 4px;
}
.grid {
row-gap: 1rem;
}
.grid .grid {
background: green;
}
.grid-breakout {
background: red;
}
.container {
-webkit-column-gap: 1rem;
column-gap: 1rem;
row-gap: 1rem;
margin-bottom: 1rem;
}
<div class="container">
<div class="grid">
<div class="col-4"></div>
<div class="col-4">
<div class="grid">
<div class="col-12"></div>
<div class="col-3"></div>
<div class="col-9"></div>
<div class="col-2"></div>
<div class="col-10"></div>
<div class="col-1"></div>
<div class="col-11"></div>
</div>
</div>
<div class="col-4"></div>
<div class="col-4"></div>
</div>
<div class="grid">
<div class="col-6">
<p>This is what I would want to happen...</p>
<div class="grid">
<div class="col-12"></div>
<div class="col-3"></div>
<div class="col-9"></div>
<div class="col-2"></div>
<div class="col-10"></div>
<div class="col-1"></div>
<div class="col-11"></div>
</div>
</div>
<div class="col-6">
<div class="grid">
<div class="col-4"></div>
<div class="col-8"></div>
</div>
</div>
</div>
</div>
Short answer.
Bear in mind, that for any given grid, you should never have gaps that multiplied by the columns will have bigger size than the container grid even when the columns has no content.
In other words: gap * columns(0width) < gridWidth otherwise, it will overflow.
Try to reduce the gap for inner grids from 2rem to 1rem for instance and your example will work
.main {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(12, 1fr);
margin: 0 auto;
width: 100%;
max-width: 1280px;
}
.one, .two, .three, .four, .five, .six,
.seven, .eight, .nine, .ten, .eleven, .twelve {
grid-column-end: span 12;
}
.nested {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(12, 1fr);
}
.merge-two-rows { grid-row-end: span 2 }
.merge-three-rows { grid-row-end: span 3 }
.merge-four-rows { grid-row-end: span 4 }
.merge-five-rows { grid-row-end: span 5 }
.merge-six-rows { grid-row-end: span 6 }
#media only screen and (min-width: 481px) {
.one { grid-column-end: span 1 }
.two { grid-column-end: span 2 }
.three { grid-column-end: span 3 }
.four { grid-column-end: span 4 }
.five { grid-column-end: span 5 }
.six { grid-column-end: span 6 }
.seven { grid-column-end: span 7 }
.eight { grid-column-end: span 8 }
.nine { grid-column-end: span 9 }
.ten { grid-column-end: span 10 }
.eleven { grid-column-end: span 11 }
}
Resource: Smart 12 Column Grid with Nesting

grid item span won't span more than 1 column

The orange box won't span more than one column no matter what I set the "grid-column" to be.
Why is that?
I have tried the following: combinations: (It's the .hr-3 item)
grid-column: 6 / span 9;
grid-column: 6 / 9;
grid-column: 2 / 7;
grid-column: 2 / span 9;
I triple checked that I am targeting the right item.
Nothing seems to work..
#import url('https://fonts.googleapis.com/css?family=Montserrat|Teko');
html, body {
background: transparent;
width: 100%;
height: 100%;
}
#a {
margin: 50px 0 0 50px;
width: 70%;
height: 70%;
background: rgb(250,250,250);
display: grid;
grid-template-columns: auto auto 1px auto repeat(6, 2fr);
grid-template-rows: auto repeat(9,1fr);
//transform: rotate(-45deg);
grid-gap: 5px;
}
.item {
//background: rgba(100,100,0,0.02);
font-family: 'Montserrat', sans-serif;
}
.item-1 {
grid-column: 1 / 2;
grid-row: 1 / 2;
}
.item-2 {
grid-column: 2 / 3;
grid-row: 1 / span 3;
writing-mode: vertical-rl;
text-orientation: upright;
display: flex;
align-items: center;
padding-top: 3px;
}
.item-3 {
grid-column: 4 / 5;
grid-row: 1 / span 3;
writing-mode: vertical-rl;
text-orientation: upright;
display: flex;
align-items: center;
padding-top: 3px;
}
.item-4 {
grid-column: 5 / 6;
grid-row: 1 / 1;
}
.hr-1 {
grid-column: 3 / 4;
grid-row: 2 / span 3;
background: rgba(0,0,0,0.9);
}
.hr-2 {
grid-column: 6 / 7;
grid-row: 1 / span 8;
border-left: 25px solid red;
}
.hr-3 {
grid-column: 6 / span 9; // <------- DOESN'T WORK?
grid-row: 6/8;
border: 25px solid orange;
}
<div id="a">
<div class="item item-1"><b>John</b></div>
<div class="item item-2"><b>A</b>lexander</div>
<hr class="hr-1"/>
<div class="item item-3"><b>B</b>lue</div>
<div class="item item-4"><b>Peterson</b></div>
<div class="item item-5"></div>
<hr class="hr-2"/>
<hr class="hr-3"/>
<hr class="hr-4"/>
</div>
hr has a default margin set that is creating the issue. Make them equal to 0.
The default margin is set to auto so it's aligning your item (an empty one) inside the track which make you think your element isn't spaning the needed columns. What you will see in all the case is the 50px border you made (left+right)
#import url('https://fonts.googleapis.com/css?family=Montserrat|Teko');
html, body {
background: transparent;
width: 100%;
height: 100%;
}
#a {
margin: 50px 0 0 50px;
width: 70%;
height: 70%;
background: rgb(250,250,250);
display: grid;
grid-template-columns: auto auto 1px auto repeat(6, 2fr);
grid-template-rows: auto repeat(9,1fr);
//transform: rotate(-45deg);
grid-gap: 5px;
}
.item {
//background: rgba(100,100,0,0.02);
font-family: 'Montserrat', sans-serif;
}
.item-1 {
grid-column: 1 / 2;
grid-row: 1 / 2;
}
.item-2 {
grid-column: 2 / 3;
grid-row: 1 / span 3;
writing-mode: vertical-rl;
text-orientation: upright;
display: flex;
align-items: center;
padding-top: 3px;
}
.item-3 {
grid-column: 4 / 5;
grid-row: 1 / span 3;
writing-mode: vertical-rl;
text-orientation: upright;
display: flex;
align-items: center;
padding-top: 3px;
}
.item-4 {
grid-column: 5 / 6;
grid-row: 1 / 1;
}
.hr-1 {
grid-column: 3 / 4;
grid-row: 2 / span 3;
background: rgba(0,0,0,0.9);
}
.hr-2 {
grid-column: 6 / 7;
grid-row: 1 / span 8;
border-left: 25px solid red;
}
.hr-3 {
grid-column: 6 / span 9;
grid-row: 6/8;
border: 5px solid orange;
}
hr {
margin:0;
}
<div id="a">
<div class="item item-1"><b>John</b></div>
<div class="item item-2"><b>A</b>lexander</div>
<hr class="hr-1"/>
<div class="item item-3"><b>B</b>lue</div>
<div class="item item-4"><b>Peterson</b></div>
<div class="item item-5"></div>
<hr class="hr-2"/>
<hr class="hr-3"/>
<hr class="hr-4"/>
</div>
Here is what you can see using the dev tools and by keeping the default margin:
You can see that the element is taking 9 column and 2 rows and the margin is centering everything inside.

Sticky header on css grid

I've got a nifty responsive css template using css grids and I'd like to make the header of this responsive css grid sticky, but because of the way the header and nav is designed, I can't get it to use fixed positioning.
is there a better way of doing this with some grid property I might not have seen yet?
* {
margin: 0;
padding: 0;
}
body {
display: grid;
font-family: sans-serif;
}
a {
text-decoration: none;
color: white;
}
header,
nav {
background: blue;
color: #fff;
position: fixed;
}
nav {
display: flex;
flex-wrap: wrap;
align-items: center;
}
nav span {
margin-right: auto;
}
header {
display: none;
}
aside {
background: lightgreen;
}
main {
background: pink;
}
/* mobile */
#media (max-width: 767px) {
body {
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
nav,
aside,
main {
grid-column: 1 / 1;
padding: 0 15px;
}
}
/* tablets */
#media (min-width: 768px) {
body {
grid-template-columns: 275px 1fr;
grid-template-rows: 1fr 1fr;
}
nav {
grid-column: 1 / 4;
grid-row: 1;
height: 50px;
grid-row: 1;
}
aside {
grid-column: 1;
}
main {
grid-column: 2;
}
nav,
aside,
main {
padding: 0 15px;
}
}
/* desktops */
#media (min-width: 992px) {
body {
grid-template-columns: 10% 275px 1fr 10%;
grid-template-rows: 1fr 1fr;
}
header {
display: block;
grid-column: 1 / -1;
grid-row: 1;
}
nav {
grid-column: 2 / 4;
grid-row: 1;
}
aside {
grid-column: 2 / 3;
}
main {
grid-column: 3 / 4;
}
}
/* xl desktops */
#media (min-width: 1920px) {
body {
grid-template-columns: 1fr minmax(auto, 300px) minmax(auto, 1620px) 1fr;
grid-template-rows: 1fr 1fr;
}
}
<header></header>
<nav>
<span>Logo</span>
login
</nav>
<aside>aside</aside>
<main>main</main>
https://jsfiddle.net/90kotz8d/3/
Using position: fixed; will take it out of the flow, and thus won't be part of your grid system. To achieve this, you can use the non-standard position: sticky; with top: 0;, the fallback being it behaving like a non-sticky element.
Here, I'm assuming the nav element is your header, since your header is set to display: none; but the position property can be moved to any element of your grid (why put header in your markup if you're not going to show it?)
* {
margin: 0;
padding: 0;
}
body {
display: grid;
font-family: sans-serif;
}
a {
text-decoration: none;
color: white;
}
header,
nav {
background: blue;
color: #fff;
position: fixed;
}
nav {
position: -webkit-sticky;
position: sticky;
top: 0;
display: flex;
flex-wrap: wrap;
align-items: center;
}
nav span {
margin-right: auto;
}
header {
display: none;
}
aside {
background: lightgreen;
}
main {
background: pink;
}
/* mobile */
#media (max-width: 767px) {
body {
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
nav,
aside,
main {
grid-column: 1 / 1;
padding: 0 15px;
}
}
/* tablets */
#media (min-width: 768px) {
body {
grid-template-columns: 275px 1fr;
grid-template-rows: 1fr 1fr;
}
nav {
grid-column: 1 / 4;
grid-row: 1;
height: 50px;
grid-row: 1;
}
aside {
grid-column: 1;
}
main {
grid-column: 2;
}
nav,
aside,
main {
padding: 0 15px;
}
}
/* desktops */
#media (min-width: 992px) {
body {
grid-template-columns: 10% 275px 1fr 10%;
grid-template-rows: 1fr 1fr;
}
header {
display: block;
grid-column: 1 / -1;
grid-row: 1;
}
nav {
grid-column: 2 / 4;
grid-row: 1;
}
aside {
grid-column: 2 / 3;
}
main {
grid-column: 3 / 4;
}
}
/* xl desktops */
#media (min-width: 1920px) {
body {
grid-template-columns: 1fr minmax(auto, 300px) minmax(auto, 1620px) 1fr;
grid-template-rows: 1fr 1fr;
}
}
<header></header>
<nav>
<span>Logo</span>
login
</nav>
<aside>aside</aside>
<main>main</main>

Resources