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>
Related
Can anyone tell me if there is any framework used to write this CSS Snippet or it's pure CSS. The reason I am asking is because it's differently formated than what I have seen. Code below:
.hero { padding-block-start: calc(var(--section-padding) + 80px); }
.hero .container {
grid-template-columns: 0.8fr 1fr;
align-items: center;
gap: 100px;
}
.hero-content { text-align: left; }
.hero .btn-wrapper { justify-content: flex-start; }
/**
* ABOUT
*/
.about .wrapper {
grid-template-columns: 1fr 1fr;
align-items: center;
}
.about .grid-list { grid-template-columns: repeat(4, 1fr); }
/**
* PROJECT
*/
.project .grid-list {
grid-template-columns: 1fr 1fr;
row-gap: 50px;
}
.project .grid-list > li:nth-child(-n+2) { grid-column: 1 / 3; }
.project-card-1,
.project-card-2 {
flex-direction: row;
align-items: flex-end;
}
:is(.project-card-1, .project-card-2) .card-content { width: 33.33%; }
:is(.project-card-1, .project-card-2) .card-banner { width: 66.66%; }
.project-card-1 .card-content { padding-block-end: var(--padding); }
.project-card-2 .card-content { order: 1; }
Just wondering if there is any framework involved as usually css is structured like:
.header {
color: white;
}
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
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>
How do I expand the inner most grid to take up more space to the right. I want it to be the same width from its left side. There is a big gap to the right of the inner most div. The entire project can be see at this codepen: https://codepen.io/centem/pen/oNvZLgP?editors=1100
CSS
.inner-header {
background-color: #96ceb4;
}
.header :nth-child(2) {
padding: 0 40px;
}
.inner-menu {
background-color: #ff6f69;
}
.inner-content {
background-color: #ffcc5c;
}
.inner-footer {
background-color: #88d8b0;
}
.inner-grid-page > div {
color: #ffeead;
display: flex;
align-items: center;
padding: 0px 20px;
}
.inner-grid-page {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 20px 150px 20px;
}
.inner-header {
grid-column: span 12;
display: flex;
}
.inner-header > div:nth-child(3) {
margin-left: auto;
}
.inner-menu {
grid-column: span 2;
}
.inner-content {
grid-column: span 10;
}
.inner-footer {
grid-column: span 12;
}
We can just add width: 100% -:
.inner-grid-page {
display: grid;
width: 100%;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 20px 150px 20px;
}
For item inside flex, if you want it to take up space set flex-grow: 1 or flex: 1
.inner-grid-page {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 20px 150px 20px;
flex: 1;
}
I am exploring CSS Grid and I am having trouble because the size doesn't use full height and my HTML and body is [width, height 100%]. I have a large white section how do I make it snap to whatever is top?
Any suggestion will be appreciated.
Here is my CSS.
*,** {
margin: 0 !important;
padding: 0 !important;
box-sizing: border-box;
}
html{
margin: 0;
padding:0;
width: 100%;
height: auto;
}
.grid {
margin: 0;
display: grid;
grid-template-columns: 100%;
grid-template-rows: repeat(auto, 4);
/* grid-template-rows: 13% auto 20%; */
grid-template-areas:
"header"
"main";
#media screen and (min-width: 500px) {
grid-template-columns: auto;
grid-template-rows: repeat(auto, 3);
grid-template-areas:
"header header"
"main main"
"main main";
}
#media screen and (min-width: 800px) {
grid-template-columns: 30% auto;
grid-template-rows: repeat(auto, 3);
grid-template-areas:
"header header"
"sidebar main"
"sidebar2 main";
}
A concern is if I mess with positions it makes things fly left...
You can use vh units, calc and min-height like:
header { grid-area: header; height: 80px; }
nav { grid-area: sidebar; }
main { grid-area: main; min-height: calc(100vh - 80px); } /* subtract header height */
aside { grid-area: sidebar2; }
Here is an example (I've changed the sizes a bit to work on stackoverflow):
*, ** {
margin: 0 !important;
padding: 0 !important;
box-sizing: border-box;
}
html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
body {
margin: 0;
min-height: 100%;
}
.grid {
margin: 0;
display: grid;
min-height: 100vh;
grid-template-columns: 100%;
grid-template-rows: repeat(auto, 4);
/* grid-template-rows: 13% auto 20%; */
grid-template-areas: "header" "main";
}
#media screen and (min-width: 200px) {
.grid {
grid-template-columns: auto;
grid-template-rows: repeat(auto, 3);
grid-template-areas: "header header" "main main" "main main";
}
}
#media screen and (min-width: 400px) {
.grid {
grid-template-columns: 30% auto;
grid-template-rows: repeat(auto, 3);
grid-template-areas: "header header" "sidebar main" "sidebar2 main";
}
}
header {
background: tomato;
grid-area: header;
height: 40px;
}
nav {
background: gold;
grid-area: sidebar;
}
main {
background: olive;
grid-area: main;
min-height: calc(100vh - 40px);
}
aside {
background: orange;
grid-area: sidebar2;
}
<div class="grid">
<header>Header</header>
<nav>Sidebar</nav>
<main>Main</main>
<aside>Sidebar 2</aside>
</div>