I've got little styling issues with a simple grid layout, containing a sidebar (aside) and some main content.
<body>
<header>Header</header>
<nav>Navigation Links</nav>
<aside>Sidebar</aside>
<main>Some main content</main>
<footer>Footer</footer>
</body>
On some pages there is no aside included in my html:
<body>
<header>Header</header>
<nav>Navigation Links</nav>
<main>Some main content</main>
<footer>Footer</footer>
</body>
Here is my code
body {
height: 100%;
display: grid;
/* mobile layout */
grid-template: auto auto auto 1fr auto / 1fr;
grid-template-areas:
"header"
"nav"
"aside"
"main"
"footer";
}
header {
background-color: blue;
grid-area: header;
}
nav {
background-color: aquamarine;
grid-area: nav;
}
aside {
background-color: green;
grid-area: aside;
}
main {
background-color: yellow;
grid-area: main;
}
footer {
background-color: orange;
grid-area: footer;
}
/* desktop layout */
#media (min-width: 768px) {
body {
grid-template: auto auto 1fr auto / minmax(300px, 25%) 1fr;
grid-template-areas:
"header header"
"nav nav"
"aside main"
"footer footer";
}
}
<body>
<header>Header</header>
<nav>Navigation Links</nav>
<!-- if aside is deleted main should strech whole space-->
<aside>Sidebar</aside>
<main>Some main content</main>
<footer>Footer</footer>
</body>
If the sidebar is displayed, it should have a minimum width of 300px. If sidebar is not displayed main content should take the whole width. However its not possible, its still taking only 75% of the width (25% are max for aside).
Some solutions i thought about:
If no aside is displayed, I could adjust grid-template to use only one grid column:
grid-template: auto auto auto 1fr auto / 1fr;
However, I do not know how accomplish this with CSS. :has selector is still working draft.
Set width for first grid column to 0.
grid-template: auto auto 1fr auto / 0 1fr;
However, how can I override this setting if aside is displayed?
Thanks for your help!
Define the width inside the aside element and keep auto in the template. Since you are dealing with a full width/height grid, you can consider the use of 25vw instead of 25%.
You have to aslo consider the mobile layout and correctly place both main and footer
body {
height: 100vh;
margin: 0;
display: grid;
grid-template: auto auto auto 1fr auto / 1fr;
}
header { background-color: blue;}
nav { background-color: aquamarine;}
aside { background-color: green;}
main { background-color: yellow;grid-row:4}
footer { background-color: orange;grid-row:5}
/* desktop layout */
#media (min-width: 768px) {
body {
grid-template: auto auto 1fr auto / auto 1fr;
grid-template-areas: "header header" "nav nav" "aside main" "footer footer";
}
aside {
width: min(300px, 25vw);
}
header { grid-area: header;}
nav { grid-area: nav; }
aside { grid-area: aside;}
main { grid-area: main;}
footer {grid-area: footer;}
}
<body>
<header>Header</header>
<nav>Navigation Links</nav>
<!-- if aside is deleted main should strech whole space-->
<aside>Sidebar</aside>
<main>Some main content</main>
<footer>Footer</footer>
</body>
Use fit-content() and specify a min-width for aside:
body {
margin: 0;
min-height: 100vh;
}
.grid {
height: 100vh;
display: grid;
/* mobile layout */
grid-template-columns: 1fr;
grid-template-rows: repeat(3, auto) 1fr auto;
grid-template-areas:
"header"
"nav"
"aside"
"main"
"footer";
}
header {
background-color: blue;
grid-area: header;
}
nav {
background-color: aquamarine;
grid-area: nav;
}
aside {
background-color: green;
grid-area: aside;
min-width: 300px;
}
main {
background-color: yellow;
grid-area: main;
}
footer {
background-color: orange;
grid-area: footer;
}
/* desktop layout */
#media (min-width: 768px) {
.grid {
grid-template-columns: fit-content(300px) 1fr;
grid-template-rows: repeat(2, auto) 1fr auto;
grid-template-areas:
"header header"
"nav nav"
"aside main"
"footer footer";
}
}
<div class="grid">
<header>Header</header>
<nav>Navigation Links</nav>
<!-- if aside is deleted main should strech whole space-->
<aside>Sidebar</aside>
<main>Some main content</main>
<footer>Footer</footer>
</div>
<div class="grid">
<header>Header</header>
<nav>Navigation Links</nav>
<main>Some main content</main>
<footer>Footer</footer>
</div>
Related
In the attached snippet, the "header" section of the grid has text that is aligned to the left. How can I go about adding additional text that is aligned to the far right section of the grid? Also, I am wondering how to go about centering the text vertically, as it currently is above the middle. I have tried adding another div and using justify-content and align-items, but nothing I have tried so far has worked. Would appreciate any help. Thank you.
body {
display: grid;
grid-template-areas: "header header header" "nav article ads" "nav footer footer";
grid-template-rows: 80px 1fr 70px;
grid-template-columns: 20% 1fr 15%;
grid-row-gap: 10px;
grid-column-gap: 10px;
height: 100vh;
margin: 0;
}
header,
footer,
article,
nav,
div {
padding: 1.2em;
background: gold;
}
#pageHeader {
grid-area: header;
}
#pageFooter {
grid-area: footer;
}
#mainArticle {
grid-area: article;
}
#mainNav {
grid-area: nav;
}
#siteAds {
grid-area: ads;
}
/* Stack the layout on small devices/viewports. */
#media all and (max-width: 575px) {
body {
grid-template-areas: "header" "article" "ads" "nav" "footer";
grid-template-rows: 80px 1fr 70px 1fr 70px;
grid-template-columns: 1fr;
}
}
<header id="pageHeader">Header</header>
<article id="mainArticle">Article</article>
<nav id="mainNav">Nav</nav>
<div id="siteAds">Ads</div>
<footer id="pageFooter">Footer</footer>
You can create left and right <div> elements inside your header, then give the header the following styles:
#pageHeader {
display: flex;
align-items: center; /*center children*/
justify-content: space-between; /*separate children*/
}
See the example snippet below:
body {
display: grid;
grid-template-areas: "header header header" "nav article ads" "nav footer footer";
grid-template-rows: 80px 1fr 70px;
grid-template-columns: 20% 1fr 15%;
grid-row-gap: 10px;
grid-column-gap: 10px;
height: 100vh;
margin: 0;
}
header,
footer,
article,
nav,
div {
padding: 1.2em;
background: gold;
}
#pageHeader {
grid-area: header;
display: flex;
align-items: center;
justify-content: space-between;
}
#pageFooter {
grid-area: footer;
}
#mainArticle {
grid-area: article;
}
#mainNav {
grid-area: nav;
}
#siteAds {
grid-area: ads;
}
/* Stack the layout on small devices/viewports. */
#media all and (max-width: 575px) {
body {
grid-template-areas: "header" "article" "ads" "nav" "footer";
grid-template-rows: 80px 1fr 70px 1fr 70px;
grid-template-columns: 1fr;
}
}
<!doctype html>
<title>CSS Grid Template 1</title>
<link rel="stylesheet" href="style.css">
<body>
<header id="pageHeader">
<div class="left">Header left</div>
<div class="right">Header right</div>
</header>
<article id="mainArticle">Article</article>
<nav id="mainNav">Nav</nav>
<div id="siteAds">Ads</div>
<footer id="pageFooter">Footer</footer>
</body>
Make the header element a flex container and then use
justify-content: space-between;
to align "Header" text on the left side and the additional text on the right side.
To vertically center the contents of the header, use
align-items: center;
You need to change the HTML structure of of header element as shown below:
<header id="pageHeader">
<span>Header</span>
<span>I will be on right side</span>
</header>
and the CSS to get the desired layout:
header {
display: flex;
justify-content: space-between;
align-items: center;
}
Output:
I can't seem to figure out why my grid will not fill out the entire (or at least more of the) screen. I can't seem to make the grid fill out the screen more, so that the white space on the left and right side does not take up so much of the screen space on bigger monitors.
#media only screen and (max-width:970px){
.billedebar{display: none;}
}
/*Tablets, Ipads osv*/
#media only screen and (min-width:600px){
#content{
margin-left: auto;
margin-right: auto;
max-width: 970px;
display: grid;
grid-template-columns:repeat(auto-fill,1fr);
grid-auto-rows:minmax(100px,auto);
grid-gap: 10px;
grid-template-areas:
"header header header header"
"main main main main"
"main main main main"
"main main main main"
"billedebar billedebar billedebar billedebar"
"boks01 boks01 boks02 boks02"
"boks03 boks03 boks04 boks04"
"footer footer footer footer";
} }
/*DESKTOP/LAPTOP*/
#media only screen and (min-width:970px){
#content{
margin-left: auto;
margin-right: auto;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-auto-rows: minmax(100px,auto);
grid-gap: 10px;
grid-template-areas:
"header header header header"
"header header header header"
"billedebar main main main"
"billedebar main main main"
"billedebar main main main"
"boks01 boks02 boks03 boks04"
"boks01 boks02 boks03 boks04"
"footer footer footer footer"
"footer footer footer footer";
}
.billedebar{
display: block;
}
}
#content div{
background: #3498db;
padding: 10px; /*tekst i grid paddes ind fra kant*/
color: white; }
.header{
grid-area: header;
}
.billedebar{
grid-area: billedebar;
}
.main{
grid-area: main;
}
.section{
grid-area: bigad;
}
.boks01{
grid-area: boks01;
}
.boks02{
grid-area: boks02;
}
.boks03{
grid-area: boks03;
}
.boks04{
grid-area: boks04;
}
.footer{
grid-area: footer;
}
<body>
<div id="content">
<div class="header"><p>header</p></div>
<div class="billedebar">billedebar</div>
<div class="main">main</div>
<div class="boks01">ad</div>
<div class="boks02">ad</div>
<div class="boks03">ad</div>
<div class="boks04">ad</div>
<div class="footer">footer</div>
</div>
</body>
You're setting max-width: 970px; on #content.
The red sidebar in this page needs to be 100% of the container height:
body {
display: grid;
min-height: 85vh;
grid-template-columns: auto 10fr 4fr;
grid-template-rows: minmax(1rem, max-content) 1fr minmax(1rem, max-content);
grid-template-areas: "header header aside" "main main aside" "footer footer footer";
}
header {
grid-area: header;
background: pink;
}
footer {
grid-area: footer;
background: blue;
}
main {
grid-area: main;
background: green;
}
aside {
grid-area: aside;
background: red;
height: 100px;
overflow-y: scroll;
}
<header> header </header>
<main>main</main>
<aside>
aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>
</aside>
<footer> footer </footer>
Can this be achieved without adding another inner element with 100% height absolute position ?
note that I added 100px height to it just to point out that it needs to be scrollable. But I want the height to be 100% of container...
Use min-height: 100%;height:0; to avoid the height of the aside affecting the layout then force it to be 100% height at the same time (height of its track defined by the other content)
body {
display: grid;
min-height: 85vh;
grid-template-columns: auto 10fr 4fr;
grid-template-rows:
minmax(1rem, max-content) 1fr minmax(1rem, max-content);
grid-template-areas:
"header header aside"
"main main aside"
"footer footer footer";
}
header {
grid-area: header;
background: pink;
}
footer {
grid-area: footer;
background: blue;
}
main {
grid-area: main;
background: green;
}
aside {
grid-area: aside;
background: red;
min-height: 100%;
height:0;
overflow-y: scroll;
}
<header> header </header>
<main>main</main>
<aside>
aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>
</aside>
<footer> footer </footer>
You can add the exact height that uses on the grid container and then add overflow-y: scroll
body {
display: grid;
min-height: 75vh;
grid-template-columns: auto 10fr 4fr;
grid-template-rows: minmax(1rem, max-content) 1fr minmax(1rem, max-content);
grid-template-areas: "header header aside" "main main aside" "footer footer footer";
}
header {
grid-area: header;
background: pink;
}
footer {
grid-area: footer;
background: blue;
}
main {
grid-area: main;
background: green;
}
aside {
height: 100%;
grid-area: aside;
background: red;
max-height: 75vh;
overflow-y: scroll;
z-index: 1;
}
<header> header </header>
<main>main</main>
<aside>
aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>aside<br>
</aside>
<footer> footer </footer>
I am stuck on two issues with my layout.
1) The two divs in header and footer don't align up (just off slightly)
2) I am using grid-areas for my main content, but can't get it to span all the way down to the footer.
https://codepen.io/anon/pen/rEZwJY?editors=1100
.grid {
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"header header header header header header header header header header header header"
"main main main main main main main main main main main main"
"footer footer footer footer footer footer footer footer footer footer footer footer"
}
.header {
background-color: pink;
grid-area: header;
grid-gap: 1em;
display: grid;
grid-template-areas:
"logo nav"
}
.main {
background-color: pink;
margin: 1em 0;
grid-area: main;
grid-gap: 1em;
display: grid;
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
}
.footer {
background-color: pink;
grid-area: footer;
grid-gap: 1em;
display: grid;
grid-template-areas:
"legal links"
}
.logo {
background-color: hotpink;
grid-area: logo;
}
.nav {
background-color: hotpink;
grid-area: nav;
}
.sidebar {
background-color: hotpink;
grid-area: sidebar;
}
.content {
background-color: hotpink;
grid-area: content;
}
.newsletter {
background-color: hotpink;
grid-area: newsletter;
}
.legal {
background-color: hotpink;
grid-area: legal;
}
.links {
background-color: hotpink;
grid-area: links;
}
.grid div {
padding: 1em;
}
<div class="grid">
<div class="header">
<div class="logo">Logo</div>
<div class="nav">Navigation</div>
</div>
<div class="main">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
<div class="newsletter">newsletter</div>
</div>
<div class="footer">
<div class="legal">Legal</div>
<div class="links">Links</div>
</div>
</div>
If you define grid-template-columns or grid-template-rows you have to specify the same amount of units in your grid-template-areas!
html, body { margin: 0; }
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"main"
"main"
"main"
"main"
"main"
"main"
"main"
"main"
"main"
"footer";
height: 100vh;
}
.header {
background-color: pink;
grid-area: header;
grid-gap: 1em;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-areas:
"logo nav";
}
.main {
background-color: pink;
margin: 1em 0;
grid-area: main;
grid-gap: 1em;
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-areas:
"sidebar content content content content newsletter";
}
.footer {
background-color: pink;
grid-area: footer;
grid-gap: 1em;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-areas:
"legal links";
}
.logo {
background-color: hotpink;
grid-area: logo;
}
.nav {
background-color: hotpink;
grid-area: nav;
}
.sidebar {
background-color: hotpink;
grid-area: sidebar;
}
.content {
background-color: hotpink;
grid-area: content;
}
.newsletter {
background-color: hotpink;
grid-area: newsletter;
}
.legal {
background-color: hotpink;
grid-area: legal;
}
.links {
background-color: hotpink;
grid-area: links;
}
.grid div {
padding: 1em;
}
<div class="grid">
<div class="header">
<div class="logo">Logo</div>
<div class="nav">Navigation</div>
</div>
<div class="main">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
<div class="newsletter">newsletter</div>
</div>
<div class="footer">
<div class="legal">Legal</div>
<div class="links">Links</div>
</div>
</div>
The two divs in header and footer don't align up
it is caused by the width of the content varies, in this case because it depends on text length and the font and font sizes etc.
Also You didn't specify columns so here's what happens:
The font here is Times New Roman default in chrome and font size is 16px
Say the container is 300px wide the word logo takes 33.77px and navigation takes 71.09px
First sum up the lengths of the content
33.77 + 71.09 = 104.86000000000001
Second subtract it from the width of the container
300 - 104.86000000000001 = 195.14
Third Split it amongst the grid items in this case we 2
195.14 / 2 = 97.57
Fourth we add that to the length of each grid item thus the container will fill up
*logo* takes 97.57 + 33.7 = 131.34
*navigation* takes 97.57 + 71.09 = 168.66
*sum equals container's width* 168.66 + 131.34 = 300
Nice, How do we fix this ?
So How can we fix this by defining explicit even widths (just because you want the footer to align with the header for some reason), or we can define columns using fr units exactly like the other answer suggested, but keep in mind that the padding also affects the content's length.
*, *:before, *:after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 300px;
}
.header {
background-color: pink;
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1em;
grid-template-areas: 'logo nav';
}
.footer {
background-color: pink;
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1em;
grid-template-areas: 'legal links'
}
.logo {
background-color: hotpink;
grid-area: logo;
}
.nav {
background-color: hotpink;
grid-area: nav;
}
.legal {
background-color: hotpink;
grid-area: legal;
}
.links {
background-color: hotpink;
grid-area: links;
}
.container div {
animation:anim 10s linear infinite alternate;
}
#keyframes anim{
0%{
padding: 0em;
}
100%{
padding: 3em;
}
}
<div class="container">
<div class="header">
<div class="logo">Logo</div>
<div class="nav">Navigation</div>
</div>
<div class="footer">
<div class="legal">Legal</div>
<div class="links">Links</div>
</div>
</div>
I am using grid-areas for my main content, but can't get it to span all the way down to the footer.
It's because you defined 12 rows yet you using just 5
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
.grid {
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"header header header header header header header header header header header header"
"main main main main main main main main main main main main"
"footer footer footer footer footer footer footer footer footer footer footer footer"
}
.header {
background-color: pink;
grid-area: header;
grid-gap: 1em;
display: grid;
grid-template-areas:
"logo nav"
}
.main {
background-color: pink;
margin: 1em 0;
grid-area: main;
grid-gap: 1em;
display: grid;
grid-template-rows: repeat(12, 1fr);
grid-template-areas:
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
"sidebar content content content content newsletter"
}
.footer {
background-color: pink;
grid-area: footer;
grid-gap: 1em;
display: grid;
grid-template-areas:
"legal links"
}
.logo {
background-color: hotpink;
grid-area: logo;
}
.nav {
background-color: hotpink;
grid-area: nav;
}
.sidebar {
background-color: hotpink;
grid-area: sidebar;
}
.content {
background-color: hotpink;
grid-area: content;
}
.newsletter {
background-color: hotpink;
grid-area: newsletter;
}
.legal {
background-color: hotpink;
grid-area: legal;
}
.links {
background-color: hotpink;
grid-area: links;
}
.grid div {
padding: 1em;
}
<div class="grid">
<div class="header">
<div class="logo">Logo</div>
<div class="nav">Navigation</div>
</div>
<div class="main">
<div class="sidebar">sidebar</div>
<div class="content">content</div>
<div class="newsletter">newsletter</div>
</div>
<div class="footer">
<div class="legal">Legal</div>
<div class="links">Links</div>
</div>
</div>
i would define a height rather than define 12 rows because you're just duplicating the height of content (which is the text in this case) 12 times
I'm wondering how css grids can make use of max-widths. In the old way, you'd use a container with wrapper class that'd set the margins.
With CSS grids, depending on how you create them, you no longer need to use containers and sometimes you have no where to add one.
I want the header to be full width, but I want the nav within it to have a max width of 80% of the screen's resolution and margin auto it, this code is similar to the way one would have done it with a wrapping container. The question is, how do I do the same with aside and main as they are not inside of a parent to set a max width with?
body {
display: grid;
grid-template-areas:
"header header"
"aside main";
grid-template-columns: 275px 1fr;
grid-template-rows: 1fr 1fr;
}
header {
grid-area: header;
border: solid 1px black;
}
header > nav {
max-width: 80%;
margin: auto;
border: solid 1px blue;
}
aside {
grid-area: aside;
}
main {
grid-area: main;
}
HTML
<html>
<body>
<header>
<nav>nav</nav>
</header>
<aside>aside</aside>
<main>main</main>
</body>
</html>
If I have to wrap them inside of a container, how will that affect the grid? If I set the max width on the html or body tag then how would I get a header that stretches the full width of the browser?
https://jsfiddle.net/6zd3o088/6/
Think of this as a FOUR column grid of
grid-template-columns: 10% 275px 1fr 10%;
Then assign your elements per the revised grid-areas
grid-template-areas:
"header header header header"
". aside main .";
body {
display: grid;
grid-template-areas: "header header header header" ". aside main .";
grid-template-columns: 10% 275px 1fr 10%;
grid-template-rows: 1fr 1fr;
margin: 0;
padding: 0;
background: lightgrey;
}
header {
grid-area: header;
background:rebeccapurple;
}
header>nav {
max-width: 80%;
margin: auto;
background: lightblue;
}
aside {
grid-area: aside;
background: lightgreen;
}
main {
grid-area: main;
background: pink;
}
<header>
<nav>nav</nav>
</header>
<aside>aside</aside>
<main>main</main>
To use a max-width with the nav respecting the value we have to take the nav out of the header so it becomes a grid-item. Then we can align it on the grid over the header.
Using minmax for inner columns we can achieve the desired result
body {
display: grid;
grid-template-columns: 1fr minmax(auto, 100px) minmax(auto, 300px) 1fr;
grid-template-rows: 1fr 1fr;
margin: 0;
padding: 0;
background: lightgrey;
}
header {
grid-column: 1/-1;
grid-row: 1;
background: rebeccapurple;
}
nav {
grid-column: 2 / 4;
grid-row: 1;
background: lightblue;
}
aside {
grid-column: 2;
background: lightgreen;
}
main {
grid-column: 3;
background: pink;
}
<header></header>
<nav>nav</nav>
<aside>aside</aside>
<main>main</main>
Demo'd here using smaller column width for reference only. Amend the max figures as desired.
Codepen