Extracting nested grids from parent grids in CSS Grid - html

I'm tinkering with CSS Grid and was wondering if it's possible to have nested grids move out of their parent grids when resizing the screen.
I've tried changing the grid-template-areas to include "subcontent" but this seems to be wrong and disrupts the grid.
As an example, I've set up the following template and would like the "subcontent" divs (pink) to replace the "profile" area when the media breakpoint is hit.
Is there any way to do this in pure CSS Grid without roping in JS?
.wrapper {
margin: auto;
width: 80%;
background-color: #e0e0e0;
display: grid;
grid-template-columns: 3fr 1fr;
grid-template-rows: 2fr 1fr 4fr;
grid-template-areas:
" title profile"
" infobar infobar "
" maincontent sidebar ";
grid-gap: 1em;
}
.space {
background-color: #eeeeee;
grid-area: space;
}
.title {
grid-area: title;
background-color: red;
}
.profile {
grid-area: profile;
background-color: orange;
}
.infobar {
grid-area: infobar;
background-color: yellow;
}
.maincontent {
grid-area: maincontent;
display: grid;
grid-template-columns: 2fr 1fr;
grid-template-rows: 1fr 1fr;
grid-template-areas:
"subcontent1 subcontent2"
"subcontent1 subcontent2";
background-color: green;
}
.subcontent1 {
grid-area: subcontent1;
background-color: pink;
margin: 10px;
}
.subcontent2 {
grid-area: subcontent2;
background-color: pink;
margin: 10px;
}
.sidebar {
grid-area: sidebar;
background-color: blue;
}
#media screen and (max-width: 900px) {
.wrapper {
grid-template-columns: 2fr 1fr 1fr;
grid-template-areas:
"title title sidebar"
"infobar infobar infobar"
"profile maincontent maincontent"
"footer footer sidebar"
;
}
.maincontent{
display: block;
}
.subcontent {
grid-area: subcontent;
}
}
<div class="wrapper">
<div class="title">Title</div>
<div class="profile">Profile</div>
<div class="infobar">Info Bar</div>
<div class="maincontent">Main Content
<div class="subcontent1">Main1</div>
<div class="subcontent2">Main2</div>
</div>
<div class="sidebar">Sidebar</div>
</div>

I'm tinkering with CSS Grid and was wondering if it's possible to have nested grids move out of their parent grids when resizing the screen.
Just like you can't extract nested flex containers so they can participate as flex items of an ancestor flex container, you can't extract nested grids to do the same thing.
You would have to make subcontent1 and subcontent2 siblings of the other grid items in your layout to re-position them.
I've tried changing the grid-template-areas to include "subcontent" but this seems to be wrong and disrupts the grid.
There's a good reason for this disruption. You've posted invalid string values.
This is good:
grid-template-areas: " title profile"
" infobar infobar "
" maincontent sidebar "
This is good, as well:
grid-template-areas: "subcontent1 subcontent2"
"subcontent1 subcontent2"
This is bad:
grid-template-areas: "title title sidebar"
"infobar infobar infobar"
"profile maincontent maincontent"
"footer footer sidebar"
Your last declaration is invalid.
String values of the grid-template-areas property must form rectangular blocks. Since sidebar appears twice in a disconnected manner, the entire layout breaks.
In contrast, try these out instead:
grid-template-areas: "title title sidebar"
"infobar infobar infobar"
"profile maincontent maincontent"
"footer footer footer"
jsFiddle demo
OR
grid-template-areas: "title title sidebar"
"infobar infobar infobar"
"profile maincontent maincontent"
"footer footer ..."
jsFiddle demo
Now the layout works. However, there's actually no footer in your HTML, so nothing will render. Regardless, the presence of an invalid string was breaking the layout.
Here are more complete explanations:
grid-template-areas with ASCII art is not working
Grid areas not laying out properly in CSS Grid

Related

HTML Grid Layout not in accordance to CSS

So I'm trying to set up a grid-formatted website page with pure HTML and CSS, as you will see in my code below.
I'm trying to alternate between two div tags going down the left hand column of Header & inner-placeholder tags.
You will see the HTML layout alignment with the grid-template-area clearly laid out, along with the number of rows as specified by grid-template-rows
So why do I get just a red box at the corner of the screen when it's fairly obvious what I want to have as per the illustration - except for a curved box followed by a straight box, followed by a curved box etc going down the left hand side?
I have tried to change the fr number to accommodate the number of rows on the left hand side.
Thank you.
Illustration
.grid{
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-areas:
"Title Title"
"Header Content"
"inner-placeholder Content"
"Header Content"
"inner-placeholder Content"
"Sidebar Content"
"Footer Footer";
grid-gap: 10px;
}
.Title{
grid-area: Title;
}
.Header{
grid-area: Header;
}
.Sidebar{
grid-area: Sidebar;
}
.Content{
grid-area: Content;
}
.Footer{
grid-area: Footer;
}
.inner-placeholder{
grid-area: inner-placeholder;
}
.grid div:nth-child(even){
background-color: red;
}
.grid div:nth-child(odd){
background-color: green;
}
<div class="grid">
<div class="Title">Title
</div>
<div class="Header">Header
</div>
<div class="inner-placeholder">
</div>
<div class="Header">Header
</div>
<div class="inner-placeholder">
</div>
<div class="Sidebar">Sidebar
</div>
<div class="Content">Content
</div>
<div class="Footer">Footer
</div>
</div>
It seems you misunderstood how grid areas work. If any grid area spans more than 1 row or column, it needs to form a square or a rectangle. Which means they also need to be in one continuous sequence as a 2x2 or 1x3 and so on, in your case you split the Header area and placeholder area between each other, which breaks the grid.
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(7, 1fr);
grid-template-areas:
"Title Title"
"Header Content"
"inner-placeholder Content"
"Header2 Content"
"inner-placeholder2 Content"
"Sidebar Content"
"Footer Footer";
grid-gap: 10px;
}
.Title {
grid-area: Title;
}
.Header {
grid-area: Header;
}
.Header2 {
grid-area: Header2;
}
.Sidebar {
grid-area: Sidebar;
}
.Content {
grid-area: Content;
}
.Footer {
grid-area: Footer;
}
.inner-placeholder {
grid-area: inner-placeholder;
}
.inner-placeholder2 {
grid-area: inner-placeholder2;
}
.grid div:nth-child(even) {
background-color: red;
}
.grid div:nth-child(odd) {
background-color: green;
}
<div class="grid">
<div class="Title">Title</div>
<div class="Header">Header</div>
<div class="inner-placeholder"></div>
<div class="Header2">Header2</div>
<div class="inner-placeholder2"></div>
<div class="Sidebar">Sidebar</div>
<div class="Content">Content</div>
<div class="Footer">Footer</div>
</div>

CSS grid and semantic HTML

I'm learning CSS grid and while trying to do my layout and use semantic html at the same time I run into some problems
https://codepen.io/oscarryz/pen/oNNBKyd
So basically I'm doing grid as 3x3 with empty space on the left and right and the content in the middle
.grid-container {
display: grid;
grid-template-columns: 1fr 40em 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas:
" . header . "
" . content . "
" . footer . ";
}
.header {
grid-area: header;
}
.content {
grid-area: content;
}
.footer {
grid-area: footer;
}
.header, .content, .footer {
border: 1px solid red;
}
<div class="grid-container">
<header>
<div class="header">header</div>
</header>
<main>
<div class="content">content</div>
</main>
<footer>
<div class="footer">footer</div>
</footer>
</div>
As can be seen in the codepen above, this is not working. If I remove the semantic tags it works, obviously there must be a correct way of doing this
Grid templates are for direct descendants.
The semantic elements should be referenced by tagname, not class:
/* changed from .header, which is a _child_ of header */
header {
grid-area: header;
}
/* changed from .content, which is a _child_ of main */
main {
grid-area: content;
}
/* changed from .footer, which is a _child_ of footer */
footer {
grid-area: footer;
}
Corrected codepen here: https://codepen.io/c_bergh/pen/eYYvOmG
You've assigned grid areas to your non-semantic elements in your CSS. That's why the semantic elements are interfering with your grid — because they ended up not participating in your grid at all. If you had started out with the non-semantic structure, then migrated to semantic elements, this may have been a step you missed.
Assigning the grid areas to your semantic elements allows you to remove the non-semantic ones instead, completing this migration:
html,
body,
.grid-container {
height: 100%;
margin: 0;
}
.grid-container * {
border: 1px solid red;
position: relative;
}
.grid-container {
display: grid;
grid-template-columns: 1fr 40em 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas:
" . header . "
" . content . "
" . footer . ";
}
header {
grid-area: header;
}
main {
grid-area: content;
}
footer {
grid-area: footer;
}
<div class="grid-container">
<header>header</header>
<main>content</main>
<footer>footer</footer>
</div>

Split a sidebar in top and bottom on mobile with CSS grid

Is it possible to split a sidebar with css grids on mobile but treat it kind of one on desktop?
On mobile I want everything stacked Intro Part of the sidebar Content and then the rest of the Sidebar.
On desktop I would like Intro and Content stacked in one column and the 2 sidebars stacked next to them.
The closes I got was
grid-template-areas:
"intro"
"sidebarTop"
"content"
"sidebarBottom";
#media (min-width: 600px) {
grid-template-areas:
"intro sidebarTop"
"content sidebarTop"
"content sidebarBottom";
}
But sidebarTop always takes up as much space as it can.
I want it to only use the space it uses and let the sidebarBottom take up the rest.
Any suggestions?
Example
You can start with something like this, then adapt each block to your need:
main {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: repeat(4, 25%);
grid-template-areas: "intro" "sidebarTop" "content" "sidebarBottom";
grid-gap: 5px;
}
section {
box-sizing: border-box;
padding: 15px;
background-color: tomato;
color: white;
}
#media (min-width: 600px) {
main {
grid-template-columns: 1fr 1fr;
grid-template-rows: repeat(3, 33.33%);
grid-template-areas: "intro sidebarTop" "content sidebarTop" "content sidebarBottom";
}
}
<main>
<section id="intro">
intro
</section>
<section id="sidebarTop">
sidebarTop
</section>
<section id="content">
content
</section>
<section id="sidebarBottom">
sidebarBottom
</section>
</main>

Finding a way to properly implement <main> tag in this layout

I'm laying out HTML for a project, and as you can see on the joined picture, I have an issue about properly implementing <main> tag.
My layout has a content header above the sidebar and content, which prevents me from keeping the sidebar outside the main tag.
Would someone have a solution?
I tried having the sidebar code below the content in the HTML structure, and display it as shown in the picture with flexbox reverse row, but as soon as I wrap what I want inside a <main> semantic tag, everything breaks.
Use display: contents; to stop the main element having any effect on layout. Then layout its children as if they were siblings of main instead of children of it.
body {
background: black;
display: grid;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: "header header header" "content-header content-header content-header" "sidebar content content";
margin: 0;
padding: 0;
height: 100vh;
}
header {
background: #aaf;
grid-area: header;
}
main {
display: contents;
}
main header {
background: #faa;
grid-area: content-header;
}
main #content {
background: #afa;
grid-area: content;
}
aside {
background: #aff;
grid-area: sidebar;
}
<header>
header
</header>
<main>
<header>
content header
</header>
<div id="content">
content
</div>
</main>
<aside>
sidebar
</aside>

giving same css property at CSS-Grid when using html section tag

I know:
At CSS-Grid with html dives, giving same css property (border-radius: 5px; for example) to all div's in one line see this example
and I know:
at CSS-Grid with html section to give css property, border-radius: 5px; to each block see here
My question is:
How can I type the "border-radius: 5px", once and that will affects all the blocks inside the section here?
Note, I need to use the html section in order to use CSS Grid
My understanding is that you wish to have only 1 line of (border-radius: 5px;) in your CSS file and that the border-radius affects all content inside of section.
Attached you find a code snippet with a solution.
You basically need to first define each grid-area. As second step you can define the border-radius with one line.
#page {
display: grid;
width: 100vw;
height: 100vh;
grid-template-areas: "head head"
"nav main"
"nav foot";
grid-template-rows: 1fr 3fr 1fr;
grid-template-columns: 1fr 6fr;
grid-gap: 10px;
}
#page > header {grid-area: head; background-color: #8ca0ff;}
#page > nav {grid-area: nav; background-color: #ffa08c;}
#page > main {grid-area: main; background-color: #ffff64;}
#page > footer {grid-area: foot; background-color: #8cffa0;}
#page > header,
#page > nav,
#page > main,
#page > footer {
border-radius: 5px;
}
<section id="page">
<header>Header</header>
<nav>Navigation</nav>
<main>Main area</main>
<footer>Footer</footer>
</section>