Nested CSS grid - css

I'm currently working on a CSS grid layout where I want two divs in a container to be 50% width each. But I cant really figure out how.
The element nav has two divs inside it which I want to be 50% each, but using the grid-syntax. How would you do that?
Code:
$gutter: 30px;
$columns: 12;
$maxwidth: 1200px;
#container {
max-width: $maxwidth;
width: 100%;
margin: 0 auto;
display: grid;
grid-template-columns: repeat($columns, 1fr);
grid-column-gap: $gutter;
grid-template-areas: "nav" "header" "main" "footer";
}
header, nav, main, footer {
grid-column: span $columns;
}
Markup:
<div id="container">
<nav>
<div></div>
<div></div>
</nav
<header></header>
<main></main>
<footer></footer>
</div>
image:

You can simply use like this
nav {
display: grid;
grid-template-columns: 1fr 1fr;
}
nav div {
background: red;
height: 250px;
}
nav div + div {
background: green;
}
<div id="container">
<nav>
<div></div>
<div></div>
</nav>
<header></header>
<main></main>
<footer></footer>
</div>
To know more about GRID

nav {
display: grid;
grid-template-columns: repeat(2, 1fr);
}

Related

How can I place content on both the left and right sides of my header in this CSS grid?

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:

How to make a grid item stretch to full width if next element is hidden?

guys. I'm trying to understand CSS Grid and found a behaviour I thought would be simple but turned out to be a little complicated.
I need to follow a 12-column layout a have a row with 2 elements but I need these elements to fill 100% of the width if it is the single element.
I tried to use auto-fit and it almost did the job but I couldn't find a way to explicitly set 12 columns this way.
Here's a snippet of my code:
<div class="autofit">
<div class="content"></div>
<div class="banner"></div>
</div>
.autofit {
display:grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
grid-gap: 20px;
text-align: center;
}
.autofit .content{
grid-column: 1/9;
}
.autofit .banner {
grid-column: 10/-1;
}
This way the grid works as expected but if I delete the .banner element the .content doesn't stretch to fill the available space ):
Use :only-child to define and extra rule:
.autofit {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
grid-gap: 20px;
text-align: center;
margin:5px;
}
.autofit > *{
height:20px;
}
.autofit .content {
grid-column: 1/9;
background:red;
}
.autofit .banner {
grid-column: 10/-1;
background:blue;
}
.autofit > :only-child{
grid-column: 1/-1;
}
<div class="autofit">
<div class="content"></div>
<div class="banner"></div>
</div>
<div class="autofit">
<div class="content"></div>
</div>
<div class="autofit">
<div class="banner"></div>
</div>
You try this.
.grid-container {
display: grid;
}
.grid-container--fit {
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
.grid-container div{background:#ff0000;}
<div class="autofit grid-container grid-container--fit">
<div class="content">test</div>
<div class="banner">test</div>
</div>
Auto fit
<div class="autofit grid-container grid-container--fit">
<div class="content">test</div>
</div>

How to create a sticky header with CSS-grid?

I would like to make my header sticky when scrolling using CSS grid.
I have tried the solution proposed here: Sticky header on css grid
Meaning:
position: sticky;
top:0;
However it does not work...
.wrapper {
display: grid;
grid-template-areas: "header" "middle" "footer";
grid-template-rows: auto 1fr auto;
height: 100vh;
}
/* Header */
header {
order: 1;
grid-area: header;
display: grid;
grid-gap: 100px;
grid-template-areas: "logo nav";
grid-template-columns: auto 1fr;
grid-auto-flow: column;
position: sticky;
top: 0;
}
nav {
display: grid;
grid-area: nav;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
/* Middle */
.middle {
order: 2;
grid-area: middle;
display: grid;
grid-template-columns: 50px 1fr 50px;
}
.middle>* {
grid-column: 2 / -2;
}
/* Footer */
footer {
order: 3;
grid-area: footer;
display: grid;
grid-template-columns: 1fr auto 1fr;
}
.footer-links {
display: grid;
grid-column: 2 /-2;
grid-template-columns: 1fr;
grid-auto-flow: column;
align-items: center;
}
<body>
<div class="wrapper">
<!-- Header -->
<header>
<img src="img/logo_jaeaess_glitch.png" alt="Logo of the VJ Jääß (Jess de Jesus)" style="width:42px;height:42px">
<nav>
Welcome
About
Art Work
Events
</nav>
</header>
<!-- Middle -->
<section class="middle">
</section>
<footer>
<div class="footer-links">
Instagram
<p>© 2019 Jääß</p>
</div>
</footer>
</div>
</body>
Everything displays as I want it to, except that the header scroll down instead of staying fix...
(For those who wonder, I put the order just to move it within a media query at a later stage of development)
Thank you for your answers!
To make the header fixed when scrolling, you could make it position: fixed. This requires you to set a fixed height for your header. This will make the header element flow on top of the content and ignore scrolling relative to the window.
.wrapper {
/* the header will not take any vertical place so shift wrapper down a bit*/
margin-top: 3rem;
display: grid;
/*I removed the header area as we don't need it anymore and would not work with fixed position anways*/
grid-template-areas: "middle" "footer";
grid-template-rows: 1fr auto;
/*I set the wrapper height to `200vw` so its easier to see the header not scrolling. Also take maring top into account*/
height: calc(200vh - 3rem);
}
/* Header */
header {
display: grid;
grid-gap: 100px;
grid-template-areas: "logo nav";
grid-template-columns: auto 1fr;
grid-auto-flow: column;
position: fixed;
top: 0;
height: 3rem;
width: 100%;
}
nav {
display: grid;
grid-area: nav;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
/* Middle */
.middle {
order: 2;
grid-area: middle;
display: grid;
grid-template-columns: 50px 1fr 50px;
}
.middle>* {
grid-column: 2 / -2;
}
/* Footer */
footer {
order: 3;
grid-area: footer;
display: grid;
grid-template-columns: 1fr auto 1fr;
}
.footer-links {
display: grid;
grid-column: 2 /-2;
grid-template-columns: 1fr;
grid-auto-flow: column;
align-items: center;
}
<div class="wrapper">
<!-- Header -->
<header>
<img src="img/logo_jaeaess_glitch.png" alt="Logo of the VJ Jääß (Jess de Jesus)" style="width:42px;height:42px" />
<nav>
<a href="./index.html" title="Welcome" class="welcome active">Welcome</a
>
About
Art Work
Events
</nav>
</header>
<!-- Middle -->
<section class="middle"></section>
<footer>
<div class="footer-links">
<a href="https://www.instagram.com/jaeaess/" target="_blank">Instagram</a
>
<p>© 2019 Jääß</p>
</div>
</footer>
</div>
Ps.: You are kinda overusing the css grid at this moment. It is designed for 2 dimensional layouts. Your layout would be much(!) easier if you were using flexbox. Also making grid work in IE 11 is a pain.

CSS grid elements not aligned properly

seems like an easy task which Im trying to get done since hours. I cant get my grid elements vertical aligned properly. Please take a look at the fiddle to get the idea. Maybe someone could help me with this issue.
HTML
<section class="top">
<div></div>
<div></div>
</section>
<section class="bottom">
<div></div>
<div></div>
<div></div>
</section>
CSS
section {
display: grid;
grid-template-rows:auto;
margin: 40px 0 0 0
}
section.top {
grid-template-columns:2fr 1fr;
grid-column-gap: 50px;
}
section.bottom {
grid-template-columns:1fr 1fr 1fr;
grid-column-gap: 50px;
}
section div {
background:lightblue;
height:400px
}
https://jsfiddle.net/ecj1wrae/
Well, with some thinking and calculation this one here does the trick
CSS
section.top {
grid-template-columns:calc(66% + 2vw) 34%;
grid-column-gap: 2vw;
}
section.bottom {
grid-template-columns:33% 33% 34%;
grid-column-gap: 2vw;
}
https://jsfiddle.net/ecj1wrae/3/
I know this is an old question... But I had a similar problem and I thought I'd share my solution for anyone else that needs some help.
This comment helped push me in the right direction
But you're dividing space using fr units, which applies only free
space in the container. And the bottom section has 50px less free
space than the top. So they cannot be aligned in this manner
As the layout needs to consider the gaps between the columns I found it better to frame the problem as it needs to take up 2 columns of a 3 column layout instead of thinking it needs to take up 2fr of a 3fr layout.
Helpfully grid allows us to specify how many columns an element can span grid-column: span 2;
Using the html in the question we can use a span on the first div in the top section:
section {
display: grid;
margin: 40px 0 0 0;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-column-gap: 50px;
}
section.top div:first-child {
grid-column: span 2;
}
If you would like to do it with only 1 parent element, this may be a solution:
.wrapper {
display: grid;
grid-template-columns: auto auto auto auto;
grid-row-gap: 50px;
grid-column-gap: 10px;
grid-template-areas:
'item1 item1 item1 item1 item2'
'item3 item3 item4 item4 item5';
}
.wrapper > div {
background: red;
height: 400px;
}
.item1 {
grid-area: item1;
}
.item2 {
grid-area: item2;
}
.item3 {
grid-area: item3;
}
.item4 {
grid-area: item4;
}
.item5 {
grid-area: item5;
}
<div class="wrapper">
<div class="item1"></div>
<div class="item2"></div>
<div class="item3"></div>
<div class="item4"></div>
<div class="item5"></div>
</div>
A really simple solution is change the grid-column-gap by margin (if having space on the sides is not a problem):
HTML
<section class="top">
<div></div>
<div></div>
</section>
<section class="bottom">
<div></div>
<div></div>
<div></div>
</section>
CSS
section {
display: grid;
grid-template-rows:auto;
margin: 4px 0 0 0
}
section.top {
grid-template-columns:2fr 1fr;
}
section.bottom {
grid-template-columns:1fr 1fr 1fr;
}
section div {
background:lightblue;
height:400px;
margin: 5px;
}
https://codepen.io/fillsanches/pen/oNEpKWN

How to collapse the width of CSS-grid to center it in the grid-container

Is it possible to collapse the width of a CSS grid with auto-filled columns to the minimal width required to have equal width columns that are centered with respect to the grid container?
IE if I have grid defined like this:
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
and the grid-container is 800px wide, is there a way to ensure the grid itself is only 600px wide instead of 800px?
Since I'm not sure how to explain it properly I've made a fiddle: https://jsfiddle.net/mhozx4ns/10/
I'm looking for a way that makes the top container behave like the bottom one if it is wider than what is required to place all children in one row.
body {
width: 800px;
background: black;
}
.grid div {
height: 50px;
background: #ededed;
}
.css {
display: grid;
justify-content: center;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
grid-column-gap: 64px;
grid-row-gap: 64px;
background: red;
}
.manual {
width: 664px;
margin: 32px auto 0;
background: blue;
}
.manual:after {
content: '';
display: table;
width: 100%;
}
.manual.grid div {
width: 300px;
float: left;
margin-bottom: 64px;
}
.manual.grid div:nth-of-type(even) {
margin-left: 64px;
}
.manual.grid div:last-child {
margin-bottom: 0;
}
}
<div class="css grid">
<div>
</div>
<div>
</div>
<div>
</div>
</div>
<div class="manual grid">
<div>
</div>
<div>
</div>
<div>
</div>
</div>
When you say minmax(300px, 1fr) in your rule, you're saying this:
Each column must be a minimum width of 300px and a maximum width of 1fr.
The fr unit consumes free space in the grid container. So if your container is 800px wide, the fr will factor in all that space.
Also, since fr consumes all free space, justify-content, which functions by distributing free space, is rendered useless.
Why not just remove the 1fr?
body {
width: 800px;
background: black;
}
.css {
display: grid;
justify-content: center;
grid-template-columns: repeat(auto-fill, 300px);
grid-auto-rows: 50px;
grid-column-gap: 64px;
grid-row-gap: 64px;
background: red;
}
.grid div {
background: #ededed;
}
<div class="css grid">
<div></div>
<div></div>
<div></div>
</div>

Resources