I thought that when I type . (blank field) inside grid-template-areas property, .item5 will show inside under field. However it showing inside . field. Why does it works like that?
body {
margin: 0;
}
.item1 {
grid-area: header;
}
.item2 {
grid-area: content;
}
.item3 {
grid-area: left;
}
.item4 {
grid-area: footer;
}
.grid-container {
display: grid;
grid-template-columns: 300px 1fr;
grid-template-areas: "header header"
"content ."
"left ."
"footer footer"
"under under";
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 30px;
}
<div class="grid-container">
<div class="item1">1</div>
<div class="item2">2</div>
<div class="item3">3</div>
<div class="item4">4</div>
<div class="item5">5</div>
</div>
From the specification:
A sequence of one or more "." (U+002E FULL STOP), representing a null cell token.
and
A null cell token represents an unnamed area in the grid container.
unnamed area doesn't mean that an item cannot be placed there. It simply mean unnamed and the automatic placement algorithm will start from the top to the bottom so the first empty area for item5 is an unnamed area.
You can follow the full algorithm here: https://www.w3.org/TR/css-grid-1/#auto-placement-algo where you will find no restriction about unnamed area or the named one. If your item5 was alone it will get placed into the first row/column (the one named "header")
body {
margin: 0;
}
.item1 {
grid-area: header;
}
.item2 {
grid-area: content;
}
.item3 {
grid-area: left;
}
.item4 {
grid-area: footer;
}
.grid-container {
display: grid;
grid-template-columns: 300px 1fr;
grid-template-areas: "header header"
"content ."
"left ."
"footer footer"
"under under";
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 30px;
}
<div class="grid-container">
<div class="item5">5</div>
</div>
Related question where I am giving a more detailed explanation about the placement algorithm:
CSS Grid : How Auto placement algorithm works
Based on your last comment, I think that you are expecting to have grid-auto-flow: column;, but this is not the default style.
I added it to the snippet:
body {
margin: 0;
}
.item1 {
grid-area: header;
}
.item2 {
grid-area: content;
}
.item3 {
grid-area: left;
}
.item4 {
grid-area: footer;
}
.grid-container {
grid-auto-flow: column;
display: grid;
grid-template-columns: 300px 1fr;
grid-template-areas: "header header"
"content ."
"left ."
"footer footer"
"under under";
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 30px;
}
<div class="grid-container">
<div class="item1">1</div>
<div class="item2">2</div>
<div class="item3">3</div>
<div class="item4">4</div>
<div class="item5">5</div>
</div>
Related
here's my html code
<div>
<div id="navbar" class="box">Navbar</div>
<div id="sidenav " class="box">Side Navbar</div>
<div id="main " class="box">Main</div>
<div id="footer " class="box">Footer</div>
</div>
and here's my scss code
div{
display: grid;
width:100%;
height: 100%;
grid-template-columns: 25% 75% 25%;
grid-gap: 15px;
grid-template-rows:25% 50% 25% ;
// grid-gap: 15px;
grid-template-areas:
"hd hd hd "
"sd ma ma "
"ft ft ft ";
.box{
display: flex;
// text-align: center;
border: 3px solid red;
/* width:150px;
height: 150px; */
margin: auto;
align-items: center;
justify-content: center;
}
#navbar{
grid-area: hd;
}
#sidenav{
grid-area: sd;
}
#main{
grid-area: ma;
}
#footer{
grid-area: ft;
}
}
the problem is the footer div doesn't display in the bottom here's a screenshot
what i want is to make the footer display at the bottom so what seems to be the problem here
There are some issues that I found in your code which makes the layout little wonky.
grid-template-columns: 25% 75% 25%;
The column total is more than 100%, so it will not work perfectly.
I would highly recommend you to use a CSS grid generator online like https://grid.layoutit.com/
For your layout, I would also not recommend structure 3x3 (columns and rows) - As from the image you shared above it looks like the following
1 row - For "Navbar" (this doesnt need any sub columns)
1 row - For Content -> this has 2 columns 1 for "SideNav" and 1 for "Main"
1 row - For "Footer" (again you dont need sub columns)
Based on this your HTML structure will end up looking like
<div class="container">
<div class="navbar">Navbar</div>
<div class="Content">
<div class="SideNav">Side Nav</div>
<div class="Main">Main</div>
</div>
<div class="Footer">Footer</div>
</div>
And your CSS will look like this
body{
padding: 0;
margin: 0;
}
.container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 25% 50% 25%;
gap: 0px 0px;
grid-template-areas:
"navbar"
"Content"
"Footer";
}
.navbar {
grid-area: navbar;
background-color: #f5f5f5;
padding: 16px;
text-align: center;
}
.Content {
display: grid;
grid-template-columns: 360px 1fr;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-template-areas:
"SideNav Main";
grid-area: Content;
}
.SideNav {
grid-area: SideNav;
background-color: #e5e5e5;
padding: 16px;
}
.Main {
grid-area: Main;
background-color: salmon;
padding: 16px;
}
.Footer {
grid-area: Footer;
background-color: #d5d5d5;
padding: 16px;
text-align: center;
}
Here, if you check the code well, the container has 3 rows (25% - navbar, 50% - content, 25% - footer)
And then content has 2 columns (360px - Sidenav, 1fr - Main)
Hope this helps :)
You can also see the code live on my codepen : https://codepen.io/raunaqpatel/pen/WNyQqmm
Or here:
body{
padding: 0;
margin: 0;
}
.container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 25% 50% 25%;
gap: 0px 0px;
grid-template-areas:
"navbar"
"Content"
"Footer";
}
.navbar {
grid-area: navbar;
background-color: #f5f5f5;
padding: 16px;
text-align: center;
}
.Content {
display: grid;
grid-template-columns: 360px 1fr;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-template-areas:
"SideNav Main";
grid-area: Content;
}
.SideNav {
grid-area: SideNav;
background-color: #e5e5e5;
padding: 16px;
}
.Main {
grid-area: Main;
background-color: salmon;
padding: 16px;
}
.Footer {
grid-area: Footer;
background-color: #d5d5d5;
padding: 16px;
text-align: center;
}
<div class="container">
<div class="navbar">Navbar</div>
<div class="Content">
<div class="SideNav">Side Nav</div>
<div class="Main">Main</div>
</div>
<div class="Footer">Footer</div>
</div>
csstricks says, we have three property values for grid-template-areas, out of which two are . and none. I can't see any difference in the way . and none affect the grid. See following:
.grid-container {
display: grid;
grid-template-areas: "one none two three"
"four five . six" ;
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 30px;
}
.item1 {
grid-area: one;
}
.item2 {
grid-area: two;
}
.item3 {
grid-area: three;
}
.item4 {
grid-area: four;
}
.item5 {
grid-area: five;
}
.item6 {
grid-area: six;
}
<div class="grid-container">
<div class="item1">1</div>
<div class="item2">2</div>
<div class="item3">3</div>
<div class="item4">4</div>
<div class="item5">5</div>
<div class="item6">6</div>
</div>
As you can see above . and none both leave empty blocks in the grid. I also searched on MDN, but theres no explanation for the difference. So,
What is the difference between grid-template-areas: none and grid-template-areas: .?
From the specification:
Name: grid-template-areas
Value: none | <string>+
Initial: none
none is a value on its own (grid-template-areas:none) and not a value to be used like grid-template-areas:" none one". the latter will fall under the <string>+ and "none" will become a named area and is different from .
A sequence of name code points, representing a named cell token with a name consisting of its code points.
A sequence of one or more "." (U+002E FULL STOP), representing a null cell token.
Below, I am placing 6 at "none" area
.grid-container {
display: grid;
grid-template-areas: "one . two three"
"four five none six" ;
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 30px;
}
.item1 {
grid-area: one;
}
.item2 {
grid-area: two;
}
.item3 {
grid-area: three;
}
.item4 {
grid-area: four;
}
.item5 {
grid-area: five;
}
.item6 {
grid-area: none;
}
<div class="grid-container">
<div class="item1">1</div>
<div class="item2">2</div>
<div class="item3">3</div>
<div class="item4">4</div>
<div class="item5">5</div>
<div class="item6">6</div>
</div>
This said, your example will show no difference because you are explicitly placing all your items so "none" and "." will remain empty in all the case. You can put anything there, the result will be the same.
I have a layout for the whole website which is quite standard - header/footer, two side blocks and the main content in the center. Let's put footer/header away, they're not really interesting. What I want to achieve is two things:
Make adaptive layout on mobile phones by putting red block between cyan and green.
In the same time keep the layout on desktops flexible. Namely, I don't want to have extra spaces between blue and red blocks (when cyan block has a lot of content), nor I want extra spaces between cyan and green blocks (when blue block has a lot of content)
First I did it with flexbox, but bullet #1 was not possible in Flex. Now I rewrote it to using Grid and faced issues with #2.
Question - how do I make grid elements in each column "independent" from each other in terms of height (keeping the deterministic behavior, of course)?
Here is the schematic layout (top - desktop, bottom - mobile):
And here is the CodePen example (click on magenta block to check how does it behave and what's the issue)
var testing = true;
function startTime() {
if (testing) {
document.getElementById('info').innerHTML = "<br>LongLongContent<br>LongLongContent<br><br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>";
document.getElementById('content').innerHTML = "Short content (logs block should start just after me)";
} else {
document.getElementById('content').innerHTML = "<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>LongLongContent<br>";
document.getElementById('info').innerHTML = "Short content (photos block should start just after me)";
}
testing = !testing;
}
.grid-container {
display: grid;
grid-template-columns: 210px 1fr 200px;
grid-template-rows: repeat(4, auto);
gap: 0px 0px;
grid-template-areas: "header header header"
"info content sidebar"
"photos logs sidebar"
"footer footer footer";
}
.grid-container>* {
border: 1px solid red;
}
.header {
grid-area: header;
}
.info {
grid-area: info;
background-color: blue;
color: white;
}
.photos {
grid-area: photos;
background-color: red;
}
.footer {
grid-area: footer;
}
.sidebar {
grid-area: sidebar;
background-color: magenta;
}
.content {
grid-area: content;
background-color: cyan;
}
.logs {
grid-area: logs;
background-color: green;
}
<header class="grid-container">
<header class="header">Header</header>
<div class="info" id="info">Info<br>Info<br>Info<br>Info<br>Info<br>Info<br><br>Info<br></div>
<div class="photos">Photos<br>Photos<br>Photos<br>Photos<br>Photos<br></div>
<div class="content" id="content">content<br>asdasd<br><br><br>[I'm some random empty space =(]</div>
<div class="logs">logs</div>
<div class="sidebar" id="sidebar" onclick="startTime()">Click me to toggle between different sizes of content</div>
<footer class="footer">Footer</footer>
</div>
The following code shows the implementation of the structure of a variable height grid. Note that the corresponding columns must be the same height.
Using grid-template-areas: you can implement your desired structure.
Pay attention to how to implement the grid-container class
.grid-container {
display: grid;
grid-template-columns: 25% 50% 25%;
grid-gap: 0px;
background-color: black;
grid-template-areas:
"one two three"
"one four three"
"five six three"
}
With grid-template-columns: 25% 50% 25%; 3 columns are defined.
Then with
grid-template-areas:
"one two three"
"one four three"
"five six three"
3 rows are defined by 3 columns.
I used the following code for the responsive mode
#media only screen and (max-width: 600px) {
.grid-container {
display: grid;
grid-template-columns: 100%;
grid-gap: 10px;
background-color: black;
grid-template-areas:
"two"
"four"
"five"
"six"
}
}
Full code:
.grid-container {
display: grid;
grid-template-columns: 25% 50% 25%;
grid-gap: 0px;
background-color: black;
grid-template-areas: "one two three" "one four three" "five six three"
}
#one {
grid-area: one;
height: auto;
width: 100%;
background-color: blue;
}
#two {
grid-area: two;
height: 50px;
width: 100%;
background-color: yellow;
}
#three {
grid-area: three;
height: auto;
width: 100%;
background-color: #365263;
}
#four {
grid-area: four;
height: auto;
width: 100%;
background-color: aqua;
}
#five {
grid-area: five;
height: auto;
width: 100%;
background-color: red;
}
#six {
grid-area: six;
height: auto;
width: 100%;
background-color: green;
}
.grid-container>div {
text-align: center;
padding: 20px 0;
font-size: 30px;
}
#media only screen and (max-width: 600px) {
.grid-container {
display: grid;
grid-template-columns: 100%;
grid-gap: 10px;
background-color: black;
grid-template-areas: "two" "four" "five" "six"
}
}
<h1>The grid-column Property</h1>
<div class="grid-container">
<div id="one">2<br>2<br>2<br>2<br>2<br>2<br>2<br>2<br>1</div>
<div id="two"></div>
<div id="three">3</div>
<div id="four">4<br>4<br>4<br>4<br>4<br>4<br>4<br>4<br>4<br>4<br>4<br>4<br>4<br>4<br>4<br></div>
<div id="five">5</div>
<div id="six">6</div>
</div>
I am trying to achieve this, I want the nav and header tags to fill the left side.
html {
width: 100%;
overflow: hidden;
}
body {
display: grid;
grid-template-rows: 1fr 5fr 1fr;
grid-template-columns: 2fr 5fr 3fr;
grid-template-areas:
"header header"
"nav main"
"footer footer";
}
header {
background: yellowgreen;
}
nav {
background: lightblue;
}
main {
background: aliceblue;
}
footer {
background: lightgoldenrodyellow;
}
<header>Banner</header>
<nav>Navigation</nav>
<main>Main content</main>
<footer>Footer</footer>
You can try like this
.item1 { grid-area: header; }
.item2 { grid-area: menu; }
.item3 { grid-area: main; }
.item5 { grid-area: footer; }
.grid-container {
display: grid;
grid-template-areas:
'header main main main '
'menu main main main '
'menu footer footer footer ';
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
.grid-container > div {
background-color: rgba(255, 255, 255, 0.8);
text-align: center;
padding: 20px 0;
font-size: 30px;
}
<div class="grid-container">
<div class="item1">Header</div>
<div class="item2">Menu</div>
<div class="item3">Main</div>
<div class="item5">Footer</div>
</div>
Here's an example of how you could define grid-areas
html {
overflow: hidden;
}
body {
display: grid;
grid-template-rows: 25px 100px;
grid-template-columns: 80px 1fr;
grid-template-areas: "header main" "nav main" "nav footer";
}
body>header {
grid-area: header;
background-color: yellowgreen;
}
body>nav {
grid-area: nav;
background-color: lightblue;
}
body>main {
grid-area: main;
background-color: aliceblue;
}
body>footer {
grid-area: footer;
background-color: lightgoldenrodyellow;
}
<header>Banner</header>
<nav>Navigation</nav>
<main>Main content</main>
<footer>Footer</footer>
The objective is to insert side margins for wider screens, while keeping the header span the entire width.
Normally we'd write
.inner {
margin: 0 5%;
}
to get such margins, but it turns out that HTML grids are so flexible that they make side margins possible through dead grid DIVs.
But somehow using dead DIVs does not seem quite right. Is there a way to obtain side margins within a grid. I see how this can be done with a blend of flex and grid. Here I'm wondering if it can be done with grids alone.
body {
height: 100vh; margin: 0; display: flex;
}
.outer{
margin: 5px; border: 5px; padding: 5px;
display: flex;
flex-grow: 1;
}
.inner {
flex-grow: 1;
margin: 5px; border: 5px; padding: 5px; grid-gap: 5px;
display: grid;
grid-template-rows: 100px 5fr 100px;
grid-template-columns: 1fr;
grid-template-areas: "header" "content" "side";
}
#media screen and (min-width: 600px) {
.inner {
grid-template-rows: 100px 6fr;
grid-template-columns: 5fr 100px;
grid-template-areas:
"header header"
"content side";
}
}
#media screen and (min-width: 800px) {
.inner {
grid-template-rows: 100px 6fr;
grid-template-columns: 1fr 5fr 100px 1fr;
grid-template-areas:
"header header header header"
"leftmargin content side rightmargin";
}
}
.box {
padding: 10px; margin: 5px;
border: 5px solid #444;
background-color: #eee;
font-size: 150%;
position: relative;
}
.header { grid-area: header; }
.content { grid-area: content; }
.side { grid-area: side; }
.leftmargin { grid-area: leftmargin; }
.rightmargin { grid-area: rightmargin; }
<div class="outer">
<div class="inner">
<div class="box header">Header</div>
<div class="box content">Content</div>
<div class="box side">Side</div>
</div>
</div>
Use dots (.) to declare empty grid areas:
grid-template-areas:
"header header header header"
". content side .";
Example:
body {
height: 100vh;
margin: 10px;
}
.inner {
display: grid;
grid-template-rows: 100px 5fr 100px;
grid-template-columns: 1fr;
grid-template-areas: "header" "content" "side";
grid-gap: 5px;
}
#media screen and (min-width: 600px) {
.inner {
grid-template-rows: 100px 6fr;
grid-template-columns: 5fr 100px;
grid-template-areas:
"header header"
"content side";
}
}
#media screen and (min-width: 800px) {
.inner {
grid-template-rows: 100px 6fr;
grid-template-columns: 5% 5fr 100px 5%;
grid-template-areas:
"header header header header"
". content side .";
}
}
.box {
padding: 10px; margin: 5px;
border: 5px solid #444;
background-color: #eee;
font-size: 150%;
position: relative;
}
.header { grid-area: header; }
.content { grid-area: content; }
.side { grid-area: side; }
<div class="inner">
<div class="box header">Header</div>
<div class="box content">Content</div>
<div class="box side">Side</div>
</div>