Move elements from nested "CSS Grid" to the outside - html

I want to bring out the elements from a nested grid at a smaller screen width. In the example, the elements are all set to one another when the screen reaches a certain pixel width.
I would like the elements to be displayed one after the other, and to return to the original area with a larger pixel width. Probably this is a fairly simple solution but I could not find any tip yet. Maybe someone has an idea?
body {
margin: 40px;
}
.sidebar {
grid-area: sidebar;
}
.sidebar2 {
grid-area: sidebar2;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
}
.footer {
grid-area: footer;
}
.wrapper {
background-color: #fff;
color: #444;
}
.wrapper {
display: grid;
grid-gap: 1em;
grid-template-areas: "header" "sidebar" "content" "sidebar2" "footer"
}
#media only screen and (min-width: 500px) {
.wrapper {
grid-template-columns: 20% auto;
grid-template-areas: "header header" "sidebar content" "sidebar2 sidebar2" "footer footer";
}
}
#media only screen and (min-width: 600px) {
.wrapper {
grid-gap: 20px;
grid-template-columns: 120px auto 120px;
grid-template-areas: "header header header" "sidebar content sidebar2" "footer footer footer";
max-width: 600px;
}
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
font-size: 150%;
}
.header,
.footer {
background-color: #999;
}
.sidebar2 {
background-color: #ccc;
color: #444;
}
<div class="wrapper">
<div class="box header">Header</div>
<div class="box sidebar">Sidebar</div>
<div class="box sidebar2">Sidebar 2</div>
<div class="box content"> Content
<div class="box nested_sidebar">Sidebar 2</div>
<div class="box nested_sidebar">Sidebar 2</div>
</div>
<div class="box footer">Footer</div>
</div>

The grid container is the parent element.
The grid items are the child elements (and only the child elements; descendants beyond the children are not grid items).
The child elements of grid items are, well, whatever they may be, they are not children of the main container, so they are not grid items and cannot accept grid properties like their grid item parents.
Therefore, unless you want to use absolute positioning, there is no clean CSS method for moving nested elements into the main grid container.
However, how about removing the nesting? Grid is very good at allowing elements to overlap.
jsFiddle demo
.wrapper {
display: grid;
grid-template-rows: 1fr;
grid-gap: 1em;
grid-template-areas: "header"
"sidebar"
"content"
"..."
"..."
"sidebar2"
"footer"
}
#media only screen and (min-width: 500px) {
.wrapper {
grid-template-columns: 20% 1fr;
grid-template-rows: 100px repeat(3, 50px) 100px;
grid-template-areas: "header header"
"sidebar content"
"sidebar content"
"sidebar content"
"sidebar2 sidebar2"
"footer footer";
}
.nested_sidebar1 {
grid-row: 3 / 4;
grid-column: 2 / 3;
}
.nested_sidebar2 {
grid-row: 4 / 5;
grid-column: 2 / 3;
}
}
#media only screen and (min-width: 800px) {
.wrapper {
grid-gap: 20px;
grid-template-columns: 120px auto 120px;
grid-template-rows: 100px repeat(3, 50px) 100px;
grid-template-areas: "header header header"
"sidebar content sidebar2"
"sidebar content sidebar2"
"sidebar content sidebar2"
"footer footer footer";
}
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
font-size: 150%;
}
.header {
grid-area: header;
background-color: #999;
}
.sidebar {
grid-area: sidebar;
}
.sidebar2 {
grid-area: sidebar2;
background-color: #ccc;
color: #444;
}
.content {
grid-area: content;
}
.nested_sidebar1 {
background-color: orange;
}
.nested_sidebar2 {
background-color: tomato;
}
.footer {
grid-area: footer;
background-color: #999;
}
<div class="wrapper">
<div class="box header">Header</div>
<div class="box sidebar">Sidebar</div>
<div class="box sidebar2">Sidebar 2</div>
<div class="box content">Content</div>
<div class="box nested_sidebar1">Sidebar 2a</div>
<div class="box nested_sidebar2">Sidebar 2b</div>
<div class="box footer">Footer</div>
</div>

I would play around with using fr instead of % as well as including grid-template-rows to get your desired result.
If you post a wire-frame of what you're hoping to achieve I'd be happy to give it a shot.

Related

Adaptive 3-columns layout with flexible height of the items without JS?

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>

Different number of columns based on device

I'm trying to create different number of columns based on the device.
For example: on mobile I want 2-col layout and on desktop 4-col layout etc...
I've tried messing around with minmax() , but couldn't make it happen the way I want, any advice for achieving this with minmax().
would someone have the answer?
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
<div class="wrapper">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
<div class="col">4</div>
<div class="col">5</div>
<div class="col">6</div>
</div>
Not sure how you want to layout your Grid regardless you will have to use Media Queries and define each of your columns.
Example:
div class="col one">1</div>
div class="col two">2</div>
This is the mobile lay out
.wrapper {
display: grid;
grid-gap: 1em;
grid-template-areas:
"header"
"sidebar"
"content"
"sidebar2"
"footer"
}
This is the Tablet lay out
#media only screen and (min-width: 500px) {
.wrapper {
grid-template-columns: 20% auto;
grid-template-areas:
"header header"
"sidebar content"
"sidebar2 sidebar2"
"footer footer";
}
}
This is the desktop lay out
#media only screen and (min-width: 600px) {
.wrapper {
grid-gap: 20px;
grid-template-columns: 120px auto 120px;
grid-template-areas:
"header header header"
"sidebar content sidebar2"
"footer footer footer";
max-width: 600px;
}
}
Here is an example of using css grid with Media Queries. In this example, box is followed with a unique div class name. You can use that class name to layout the grid.
body {
margin: 40px;
}
.sidebar {
grid-area: sidebar;
}
.sidebar2 {
grid-area: sidebar2;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
}
.footer {
grid-area: footer;
}
.wrapper {
background-color: #fff;
color: #444;
}
.wrapper {
display: grid;
grid-gap: 1em;
grid-template-areas:
"header"
"sidebar"
"content"
"sidebar2"
"footer"
}
#media only screen and (min-width: 500px) {
.wrapper {
grid-template-columns: 20% auto;
grid-template-areas:
"header header"
"sidebar content"
"sidebar2 sidebar2"
"footer footer";
}
}
#media only screen and (min-width: 600px) {
.wrapper {
grid-gap: 20px;
grid-template-columns: 120px auto 120px;
grid-template-areas:
"header header header"
"sidebar content sidebar2"
"footer footer footer";
max-width: 600px;
}
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 10px;
font-size: 150%;
}
.header,
.footer {
background-color: #999;
}
.sidebar2 {
background-color: #ccc;
color: #444;
}
<div class="wrapper">
<div class="box header">Header</div>
<div class="box sidebar">Sidebar</div>
<div class="box sidebar2">Sidebar 2</div>
<div class="box content">Content
<br /> More content than we had before so this column is now quite tall.</div>
<div class="box footer">Footer</div>
</div>
I would use bootstrap
basic idea is
lg is used for large windows (desktop)
md is used for medium windows (desktop)
xm is used for small windows (i.e phone / tablets)
xs is used for extra small windows (i.e phone)
you can also hide any of these layouts
<div id="container">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">1</div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">2</div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">3</div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">4</div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">5</div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">6</div>
</div>

Avoiding dead DIVs in an HTML grid

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>

When using CSS grid, i don't want some grid areas to expand

I'm starting to use CSS grid. So far, so good. I want some grid areas NOT to expand when other areas do.
This is what i have now
I'm designing mobile first, then desktop. The grid on the desktop, if you notice, the 'album' area expands when the body expands. I don't want that. I want the areas 'album', 'credits', 'version' to retain the height even if the 'body' or the 'comment' area expand. In other words, when a grid area expands, the other areas height remain intact.
https://jsfiddle.net/e9n4ac5d/
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-template-areas: "body" "album" "credit" "version" "comment";
}
#media screen and (min-width: 400px) {
.grid {
grid-template-columns: 2fr 1fr;
grid-template-rows: auto;
grid-template-areas: "body album" "comment credit" "comment version";
}
}
.body {
grid-area: body;
background-color: red;
}
.album {
grid-area: album;
background-color: pink;
}
.credit {
grid-area: credit;
background-color: green;
}
.version {
grid-area: version;
background-color: yellow;
}
.comment {
grid-area: comment;
background-color: #eee;
}
<div class="grid">
<div class="body">body
<br><br><br><br><br><br>
</div>
<div class="album">album</div>
<div class="credit">credits</div>
<div class="version">version</div>
<div class="comment">comments</div>
</div>
You can change your HTML structure like this:
.grid {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
grid-template-areas: "body" "album" "credit" "version" "comment";
}
#media screen and (min-width: 400px) {
.right {
grid-area: right;
}
.grid {
grid-template-columns: 2fr 1fr;
grid-template-rows: auto;
grid-template-areas: "body right" "comment right";
}
}
.body {
grid-area: body;
background-color: red;
}
.album {
grid-area: album;
background-color: pink;
height: 50px;
}
.credit {
grid-area: credit;
background-color: green;
height: 50px;
}
.version {
grid-area: version;
background-color: yellow;
height: 50px;
}
.comment {
grid-area: comment;
background-color: #eee;
}
<div class="grid">
<div class="body">body
<br><br><br><br><br><br>
</div>
<div class="right">
<div class="album">album</div>
<div class="credit">credits</div>
<div class="version">version</div>
</div>
<div class="comment">comments</div>
</div>
Just set fixed height and width... To make it non expandable and non compressible...

Why is my content grid area longer when used on wide media?

Disclaimer: I'm not an experienced web designer.
I've been playing around with grid and have this mock up for different screen sizes but I cannot understand why the div content area grows so much taller than the nested panelwrap grid inside it? (Im testing on Chrome).
According to chrome inspector the size only grows when the content area is over 647px wide.
I just want to understand why the space occurs?
body {
margin: 1em;
}
.sidebar {
grid-area: sidebar;
}
.sidebar2 {
grid-area: sidebar2;
}
.content {
grid-area: content;
}
.header {
grid-area: header;
}
.footer {
grid-area: footer;
}
.wrapper {
background-color: #fff;
color: #444;
}
.wrapper {
margin: auto;
display: grid;
grid-gap: 1em;
grid-template-areas: "header" "sidebar" "content" "sidebar2" "footer"
}
#media only screen and (min-width: 500px) {
.wrapper {
grid-template-columns: 20% auto;
grid-template-areas: "header header" "sidebar content" "sidebar2 sidebar2" "footer footer";
}
}
#media only screen and (min-width: 600px) {
.wrapper {
grid-gap: 20px;
grid-template-columns: 120px auto 120px;
grid-template-areas: "header header header" "sidebar content sidebar2" "footer footer footer";
max-width: auto;
}
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 0.5em;
font-size: 150%;
}
.header,
.footer {
background-color: #999;
}
.sidebar2 {
background-color: #ccc;
color: #444;
}
.panelwrap {
display: grid;
padding: 0.5em;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: minmax(auto, auto);
grid-gap: 0.5em;
}
.panel {
background-color: #fff;
color: #555;
border-radius: 5px;
padding: 0.5em;
}
.tall-panel {
grid-row-end: span 2;
}
.wide-panel {
grid-column-end: span 2;
}
<div class="wrapper">
<div class="box header">Header</div>
<div class="box sidebar">Sidebar</div>
<div class="box sidebar2">Sidebar 2</div>
<div class="box content">Content
<div class="panelwrap">
<div class="panel">Panel A</div>
<div class="panel">Panel B</div>
<div class="panel tall-panel">Panel C</div>
<div class="panel">Panel D</div>
<div class="panel">Panel E</div>
<div class="panel">Panel F</div>
<div class="panel tall-panel">Panel G</div>
<div class="panel tall-panel">Panel H</div>
<div class="panel">Panel I</div>
<div class="panel">Panel J</div>
<div class="panel wide-panel">Panel K</div>
</div>
</div>
<div class="box footer">Footer</div>
</div>
I believe this may have been an issue with the Chrome browser at the time (not sure of version I used but I am now on Version 63.0.3239.84).
I've just tested the same identical code and the content area now matches the items within it. Previously when the display was > 647px wide the content area was much longer than the panels within.