Reputation: 478
I have a header that is 70px high, the main content which I want to fill the rest of the screen and then a 70px footer. I am trying to find the most simple approach of hiding a footer. This works with the footer in view - see jsfiddle
and snippet below:
* {
margin: 0;
padding: 0;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
display: grid;
margin: 0px;
grid-gap: 10px;
height: 100vh;
grid-template-columns: [side__nav] 250px [main] 1fr;
grid-template-rows: [header] 70px auto [footer] 70px;
}
.header {
grid-column: main;
grid-row: 1;
background: pink;
}
.side__nav {
grid-column: side__nav;
grid-row: 1/span 3;
background: red;
}
.content {
grid-column: main;
grid-row: 2;
background: green;
}
.footer {
grid-column: main;
grid-row: 3;
background: purple;
opacity: 0.5;
}
.a {
grid-column: col/span 2;
grid-row: row;
}
.b {
grid-column: col 3/span 2;
grid-row: row;
}
.c {
grid-column: col/span 2;
grid-row: row 2;
}
.d {
grid-column: col 3/span 2;
grid-row: row 2;
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr;
}
.e {
grid-column: 1/3;
grid-row: 1;
}
.f {
grid-column: 1;
grid-row: 2;
}
.g {
grid-column: 2;
grid-row: 2;
}
<header class="header">header</header>
<nav class="side__nav">side__nav</nav>
<content class="content">content</content>
<footer class="footer">footer</footer>
But I want to push it off screen so I can use a button to show when needed. I have tried using grid-template-rows: [header] 70px calc(100vh - 70px) [footer] 70px
which does give me the effect I want see jsfiddle
and snippet below:
* {
margin: 0;
padding: 0;
}
*, *::before, *::after {
box-sizing: border-box;
}
body {
display: grid;
margin: 0px;
grid-gap: 10px;
height: 100vh;
grid-template-columns: [side__nav] 250px [main] 1fr;
grid-template-rows: [header] 70px calc(100vh - 70px) [footer] 70px;
}
.header {
grid-column: main;
grid-row: 1;
background: pink;
}
.side__nav {
grid-column: side__nav;
grid-row: 1/span 3;
background: red;
}
.content {
grid-column: main;
grid-row: 2;
background: green;
}
.footer {
grid-column: main;
grid-row: 3;
background: purple;
opacity: 0.5;
}
.a {
grid-column: col/span 2;
grid-row: row;
}
.b {
grid-column: col 3/span 2;
grid-row: row;
}
.c {
grid-column: col/span 2;
grid-row: row 2;
}
.d {
grid-column: col 3/span 2;
grid-row: row 2;
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr;
}
.e {
grid-column: 1/3;
grid-row: 1;
}
.f {
grid-column: 1;
grid-row: 2;
}
.g {
grid-column: 2;
grid-row: 2;
}
<header class="header">header</header>
<nav class="side__nav">side__nav</nav>
<content class="content">content</content>
<footer class="footer">footer</footer>
But the problem with that is, If I use
grid-gap: 10px
I have to calculate that ingrid-template-rows
which then gets messy if I add more sections.
For instance, 3 sections will have 2 gaps, if I set the gap as 10px, the total will be 20px, plus the 70px for the footer meaning a total of 90px. If someone takes over the code they need to know that they need to add this manually to the grid-template-row
line which I know will get missed. Anyone have a simple idea that I am missing?
Upvotes: 3
Views: 626
Reputation: 42360
You can remove your footer
from the explicit grid (change your explicit grid row definition into grid-template-rows: [header] 70px 1fr
and remove grid-row: 3
from footer
) and set the grid container height to calc(100vh + 70px)
and set the implicit grid row (which is your footer
height) using grid-auto-rows: 70px
.
See demo below with vanilla CSS:
* {
margin: 0;
padding: 0;
}
*, *::before, *::after {
box-sizing: border-box;
}
body {
display: grid;
margin: 0px;
grid-gap: 10px;
height: calc(100vh + 70px); /* adding footer height */
grid-template-columns: [side__nav] 250px [main] 1fr;
grid-template-rows: [header] 70px 1fr; /* removed footer from here */
grid-auto-rows: 70px; /* implicit grid height - footer height */
}
.header {
grid-column: main;
grid-row: 1;
background: pink;
}
.side__nav {
grid-column: side__nav;
grid-row: 1/span 3;
background: red;
}
.content {
grid-column: main;
grid-row: 2;
background: green;
}
.footer {
grid-column: main;
/*grid-row: 3;*/
background: purple;
opacity: 0.5;
}
.a {
grid-column: col/span 2;
grid-row: row;
}
.b {
grid-column: col 3/span 2;
grid-row: row;
}
.c {
grid-column: col/span 2;
grid-row: row 2;
}
.d {
grid-column: col 3/span 2;
grid-row: row 2;
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr;
}
.e {
grid-column: 1/3;
grid-row: 1;
}
.f {
grid-column: 1;
grid-row: 2;
}
.g {
grid-column: 2;
grid-row: 2;
}
<header class="header">header</header>
<nav class="side__nav">side__nav</nav>
<content class="content">content</content>
<footer class="footer">footer</footer>
But again you'll have to do those messy calculations when new sections are added to the grid. A more dynamic option is to keep a grid item (zero-width adjuster
element in demo below) just for setting the layout height:
placed in the first column and spanned across the first two rows
has height: 100vh
set and pushed behind with z-index: -1
so that it doesn't affect the layout.
See demo below:
* {
margin: 0;
padding: 0;
}
*, *::before, *::after {
box-sizing: border-box;
}
body {
display: grid;
margin: 0px;
grid-gap: 10px;
grid-template-columns: [side__nav] 250px [main] 1fr;
grid-template-rows: [header] 70px 1fr; /* removed footer from here */
grid-auto-rows: 70px; /* implicit grid height - footer height */
}
.header {
grid-column: main;
grid-row: 1;
background: pink;
}
.side__nav {
grid-column: side__nav;
grid-row: 1/span 3;
background: red;
}
.content {
grid-column: main;
grid-row: 2;
background: green;
}
.footer {
grid-column: main;
/*grid-row: 3;*/
background: purple;
opacity: 0.5;
}
.a {
grid-column: col/span 2;
grid-row: row;
}
.b {
grid-column: col 3/span 2;
grid-row: row;
}
.c {
grid-column: col/span 2;
grid-row: row 2;
}
.d {
grid-column: col 3/span 2;
grid-row: row 2;
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr;
}
.e {
grid-column: 1/3;
grid-row: 1;
}
.f {
grid-column: 1;
grid-row: 2;
}
.g {
grid-column: 2;
grid-row: 2;
}
.adjuster { /* grid items spanning two rows with explicit height set */
width: 0;
position: relative;
z-index: -1;
grid-column: 1;
grid-row: 1 / span 2;
height: 100vh;
}
section { /* new sections added*/
background: cadetblue;
}
<header class="header">header</header>
<nav class="side__nav">side__nav</nav>
<content class="content">content</content>
<footer class="footer">footer</footer>
<!-- height adjuster for viewport -->
<span class="adjuster"></span>
<!-- other page sections below -->
<section></section>
<section></section>
Excerpts on implicit and explicit grids from MDN:
The implicit and explicit grid (MDN)
If you place something outside of the defined grid—or due to the amount of content, more grid tracks are needed—then the grid creates rows and columns in the implicit grid. These tracks will be auto-sized by default, resulting in their size being based on the content that is inside them.
You can also define a set size for tracks created in the implicit grid with the
grid-auto-rows
andgrid-auto-columns
properties.
You can read more about Explicit and Implicit Grids here: CSS Grid unwanted column added automatically
Upvotes: 2