Puzzled by column span in CSS grid not working as expected - css

I am trying to build a layout with a full-width header, then two 150px wide ad blocks stacked vertically on the left, the main part in the center, then two more ad blocks stacked vertically on the right, with a full-width footer at the bottom.
The code I expected to work is
.container {
display: grid;
grid-gap: 2px;
background-color: black;
padding: 2px;
min-height: 300px;
width: 100%;
margin: 0 auto;
--nav-width: 250px;
}
.container {
grid-template-columns: 150px 1fr 150px; /*Three columns - 150px for the ads; rest of screen for main */
grid-template-rows: 200px 1fr 1fr 40px;
grid-template-areas:
"header header header"
"left_ad1 main right_ad1"
"left_ad2 main right_ad2"
"footer footer footer";
}
.header {
background:PaleTurquoise;
}
.nav {
background:LightPink;
}
.content {
background:red;
}
.footer {
background:blue;
}
div {
font-size: 28px;
}
body {
text-align: center;
}
.ad {
height: 250px;
}
header {
background: LightSalmon;
}
#left_ad1 {
background:PaleTurquoise;
grid-area: left_ad1;
}
#left_ad2 {
background:PaleTurquoise;
grid-area: left_ad2;
}
#right_ad1 {
background:LightPink;
grid-area: right_ad1;
}
#right_ad2 {
background:LightPink;
grid-area: right_ad2;
}
main {
background-color: red;
grid-area: main;
}
footer {
background: LightSkyBlue;
grid-area: footer;
}
<div class="container">
<header>Header</header>
<div id="left_ad1">Left ad 1</div>
<main>Main</main>
<div id="right_ad1" class="ad">Right ad 1</div>
<div id="left_ad2" class="ad">Left ad 2</div>
<div id="right_ad2" class="ad">Right ad 2</div>
<footer>Footer</footer>
</div>
but this makes the header fill just the left-most cell of the top row.
I can get it to work by adding
header {
grid-column: 1 / 4;
}
to force the header to span the whole width of the grid, but surely that shouldn't be needed? The use of grid-template-areas: "header header header" should achieve that without the use of grid-column shouldn't it?
Confused! Any help appreciated!

You need to specify grid-area: header; on your header element.
.container {
display: grid;
grid-gap: 2px;
background-color: black;
padding: 2px;
min-height: 300px;
width: 100%;
margin: 0 auto;
--nav-width: 250px;
}
.container {
grid-template-columns: 150px 1fr 150px; /*Three columns - 150px for the ads; rest of screen for main */
grid-template-rows: 200px 1fr 1fr 40px;
grid-template-areas:
"header header header"
"left_ad1 main right_ad1"
"left_ad2 main right_ad2"
"footer footer footer";
}
div {
font-size: 28px;
}
body {
text-align: center;
}
.ad {
height: 250px;
}
header {
background: LightSalmon;
grid-area: header;
}
#left_ad1 {
background:PaleTurquoise;
grid-area: left_ad1;
}
#left_ad2 {
background:PaleTurquoise;
grid-area: left_ad2;
}
#right_ad1 {
background:LightPink;
grid-area: right_ad1;
}
#right_ad2 {
background:LightPink;
grid-area: right_ad2;
}
main {
background-color: red;
grid-area: main;
}
footer {
background: LightSkyBlue;
grid-area: footer;
}
<div class="container">
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>
<div id="left_ad1">Left ad 1</div>
<div id="left_ad2" class="ad">Left ad 2</div>
<div id="right_ad1" class="ad">Right ad 1</div>
<div id="right_ad2" class="ad">Right ad 2</div>
</div>

Related

CSS Grid - Centering header section (Logo + Menu)

I am investigating into CSS and Grid right now, as I want to learn new things. Actually, I do have a very simple question (I guess) but I am unable to resolve this. I am trying to use CSS grid for making a simple responsive design. For that purpose, I want to have a header section in which I do have a logo and a menu centered with a maximum width of 1170 px. However, I am unable to center the header-wrapper. Maybe I am doing things wrong here. For a better understanding, I just put a jsiddler here.
https://jsfiddle.net/f7ywrg93/
.wrapper {
display: grid;
grid-template-columns: auto;
grid-template-rows: 100px auto;
grid-template-areas:
"header"
"promo";
grid-gap: 10px;
}
.header {
grid-area: header;
background-color: #20262e;
color: #fff;
font-size: 14px;
}
.promo {
grid-area: promo;
background-color: #c0ff3e;
}
.wrapper-header {
display: grid;
grid-template-columns: auto auto;
grid-template-rows: auto;
grid-template-areas: "logo menu";
max-width:1170px;
grid-gap: 20px;
background-color: #447666;
}
.logo {
grid-area: logo;
place-self: start;
max-width: 300px;
background-color: #545454;
}
.menu {
grid-area: menu;
place-self: end;
background-color: #eadead;
}
<div class="wrapper">
<div class="header">
<div class="wrapper-header">
<div class="logo">Logo</div>
<div class="menu">Menu</div>
</div>
</div>
<div class="promo">Promo</div>
</div>
Hope that one can give me some give me some idea what I am doing wrong.
If you swap place-self: start and place-self: end for the logo and menu it will center them:
.wrapper {
display: grid;
grid-template-columns: auto;
grid-template-rows: 100px auto;
grid-template-areas:
"header"
"promo";
grid-gap: 10px;
}
.header {
grid-area: header;
background-color: #20262e;
position: relative;
color: #fff;
font-size: 14px;
}
.promo {
grid-area: promo;
background-color: #c0ff3e;
}
.wrapper-header {
display: grid;
grid-template-columns: auto auto;
grid-template-rows: auto;
grid-template-areas: "logo menu";
max-width:1170px;
width: 100%;
grid-gap: 20px;
margin: 0 auto;
background-color: #447666;
}
.logo {
grid-area: logo;
place-self: end;
max-width: 300px;
background-color: #545454;
}
.menu {
grid-area: menu;
place-self: start;
background-color: #eadead;
}
<div class="wrapper">
<div class="header">
<div class="wrapper-header">
<div class="logo">Logo</div>
<div class="menu">Menu</div>
</div>
</div>
<div class="promo">Promo</div>
</div>
place-self positions the elements within their respective grid blocks and not within the container element itself.

Grid item 100% height of parent

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>

Alignment not straight and rows don't span?

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

Create implicit rows in CSS grid

I have a simple CSS grid.
I would like to have the #right and the main element under each other on a mobile view (800px width).
I thought that adding this:
main,
#right {
grid-column: 2 / span 2;
}
would put the main and #right element under each other, but no such luck. It seems they both have a 100% height causing them to overlap.
So what I would like to see is:
main {
margin-top: 90%;
height: 50%;
}
#right {
height: 50%;
}
But then of course caused by the CSS grid.
https://plnkr.co/edit/J0gZRP9LUak4n6eebnhh?p=preview
body,
html {
height: 100%;
}
#grid-wrapper {
height: 100vh;
display: grid;
grid-template: "header header header" 66px "subheader subheader subheader" 55px "left main right" auto / 18.75% auto 25%;
}
header {
grid-area: header;
display: grid;
grid-template: "logo searchbar hamburgermenu" auto / 18.75% auto 25%;
}
header #logo {
grid-area: logo;
background: red;
}
header #searchbar {
grid-area: searchbar;
background: yellow;
}
header #hamburgermenu {
grid-area: hamburgermenu;
background: teal;
}
.subheader {
grid-area: subheader;
display: grid;
grid-template: ". telephone-content ." auto / 18.75% auto 25%;
background: wheat;
}
.subheader .telephone-content {
grid-area: telephone-content;
background: lightcoral;
}
#left {
grid-area: left;
background: darkgray;
}
main {
grid-area: main;
background: lightskyblue;
}
#right {
grid-area: right;
background: lightsalmon;
}
/* TABLET VIEW */
#media screen and (max-width: 1024px) {
header {
grid-template: "logo searchbar hamburgermenu" auto / 6.75% auto 25%;
}
.subheader {
grid-template: ". telephone-content ." auto / 6.75% auto 25%;
}
#grid-wrapper {
grid-template: "header header header" 66px "subheader subheader subheader" 55px "left main right" auto / 6.75% auto 25%;
}
}
/* MOBILE VIEW */
#media screen and (max-width: 800px) {
header {
grid-template: "logo searchbar hamburgermenu" auto / 66px auto 66px;
}
.subheader {
grid-template: "telephone-content telephone-content telephone-content" auto / 66px auto 66px;
}
#grid-wrapper {
grid-template: "header header header" 66px "subheader subheader subheader" 55px "left main right" auto / 6.75% auto 25%;
}
#left {
/* grid-row: 1 / span 2; */
}
#right {
/* grid-column: 2 / 3; */
}
main,
#right {
grid-column: 2 / span 2;
}
}
<div id="grid-wrapper">
<header>
<div id="logo">
<h1>Logo</h1>
</div>
<div id="searchbar">
<p>Header stuff</p>
</div>
<div id="hamburgermenu">
<h1>...</h1>
</div>
</header>
<div class="subheader">
<p class="telephone-content">Dit is telefoon informatie</p>
</div>
<aside id="left">
<h1>Left</h1>
</aside>
<main>
<h1>Content</h1>
<p>Saaie boel</p>
</main>
<aside id="right">
<h1>Right</h1>
</aside>
</div>
</div>
This is what you have in your mobile view:
#media screen and (max-width: 800px) {
#grid-wrapper {
grid-template: "header header header" 66px
"subheader subheader subheader" 55px
"left main right" auto / 6.75% auto 25%;
}
This layout produces three rows and three columns.
row heights: 66px 55px auto
column widths: 6.75% auto 25%
But you want right to appear underneath main (or vice versa?). So try this instead:
#media screen and (max-width: 800px) {
#grid-wrapper {
grid-template: "header header header" 66px
"subheader subheader subheader" 55px
"left main main" auto /* adjustment */
"left right right" auto /* new row */
/ 6.75% auto 25%;
}
https://plnkr.co/edit/X3nlF5Jx3vSdUm52DoyZ?p=preview

Is it possible to split a grid item to allow different spans?

I have an article and an aside (sidebar) element - easy, except the title and sub-heading of the article need to span the entire row. If I take the title/sub-heading out of the article, the article element is no longer semantically complete.
Is there a way, using CSS Grid, to have the format below, where Title, Sub and Content are all a part of an "Article" element, and "Aside" is the second in a 2 column grid?
From my research so far, it seems this is not possible.
You can hack your way through using nested CSS grid if you know:
The width of the aside section
The height of the title and sub heading sections
(in many layouts, these dimensions are fixed)
You can use a pseudo element that create a space for the aside element and then sneak it inside the outer grid container - check out the demo below:
body {
margin: 0;
}
* {
box-sizing: border-box;
}
article,
aside {
border: 1px solid;
display: flex;
align-items: center;
justify-content: center;
}
div {
display: grid;
grid-template-areas: "section aside";
}
section {
grid-area: section;
display: grid;
grid-template-areas: "header header" "subhead subhead" "content empty";
grid-template-rows: 50px 50px auto;
grid-template-columns: 80vw auto;
height: 100vh;
width: 100vw;
}
section article:first-child {
grid-area: header;
}
section article:nth-child(2) {
grid-area: subhead;
}
section article:last-child {
grid-area: content;
}
section:after {
content: '';
display: block;
grid-area: empty;
}
aside {
grid-area: aside;
height: calc(100vh - 100px);
width: 20vw;
align-self: flex-end;
position:relative;
transform: translateX(-100%);
}
<div>
<section>
<article>Article title</article>
<article>Article sub-heading</article>
<article>Article content</article>
</section>
<aside>Aside</aside>
</div>
You can use something like this.
* {box-sizing: border-box;}
.wrapper {
max-width: 940px;
margin: 0 auto;
}
.wrapper > div {
border: 2px solid rgb(233,171,88);
border-radius: 5px;
background-color: rgba(233,171,88,.5);
padding: 10px;
color: #d9480f;
}.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
grid-auto-rows: minmax(100px, auto);
}
.one {
grid-column: 1 / 4;
grid-row: 1;
}
.two {
grid-column: 1 / 4;
grid-row: 2;
}
.three {
grid-column: 1 / 3;
grid-row: 3;
min-height:200px;
}
.four {
grid-column: 3;
grid-row: 3;
min-height:200px;
}
<div class="wrapper">
<div class="one">One</div>
<div class="two">Two</div>
<div class="three">Three</div>
<div class="four">Four</div>
</div>
Also check Fiddle.
And for more details please visit https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout
You can achieve that by simply floating all the cells, as long as the article doesn't float - https://jsfiddle.net/yxbckzcq/1/
<div class="wrapper">
<article>
<div style="float:left;width:100%" class="one">One</div>
<div style="float:left;width:100%" class="two">Two</div>
<div style="float:left;width:70%" class="three">Three</div>
</article>
<div style="float:left;width:30%" class="four">Four</div>
</div>

Resources