Grid area with responsive not works as expect - css

:root {
--min-screen-height:100px;
}
.App {
display: grid;
grid-template-columns: 0.7fr 0.9fr 1.5fr 0.9fr;
grid-template-rows: 2.75rem 3fr;
grid-template-areas:
'nav nav nav nav'
'sidebar leftmenu content rightmenu';
gap: 0.75rem 0.4rem;
}
.navigation {
grid-area: nav;
background-color: yellow;
}
.sidebar {
min-height: var(--min-screen-height);
grid-area: sidebar;
background-color: aliceblue;
}
.leftmenu {
grid-area: leftmenu;
background-color: skyblue;
}
.content {
min-height: var(--min-screen-height);
grid-area: content;
background-color: blanchedalmond;
padding: 0.5em 0.75em 0.5em 0.75em;
}
.rightmenu {
grid-area: rightmenu;
background-color: coral;
}
#media screen and (max-width: 768px) {
.App {
grid-template-columns: 1fr;
grid-template-areas:
'nav'
'content';
}
}
<div class="App">
<div class="navigation">Nav</div>
<div class="sidebar">Side bar</div>
<div class="leftmenu">Left Menu</div>
<main class="content">Main</main>
<div class="rightmenu">Right Menu</div>
</div>
In responsive until 768px I am only showing the nav and container. But still in the 768 I could see the rightmenu.
what is wrong here? or how to fix this? Please check in full page with by resizing it.

https://www.w3.org/TR/css-grid-2/#explicit-grids
The three properties grid-template-rows, grid-template-columns, and grid-template-areas together define the explicit grid of a grid container by specifying its explicit grid tracks. The final grid may end up larger due to grid items placed outside the explicit grid; in this case implicit tracks will be created, these implicit tracks will be sized by the grid-auto-rows and grid-auto-columns properties.
The grid-auto-flow property controls auto-placement of grid items without an explicit position. Once the explicit grid is filled (or if there is no explicit grid) auto-placement will also cause the generation of implicit grid tracks.
So grid-template-areas defines explicit grid. Remaining areas are put in implicit grid.
To get rid of those elements you may use:
#media screen and (max-width: 768px) {
.App {
grid-template-columns: 1fr;
grid-template-areas: "nav" "content";
}
.App :not(.navigation, .content) {
display: none;
}
}

All the divs are still there so the grid does its best to accommodate them although they say they are in grid-areas which are not defined.
To completely get rid of them you will need to set them to display none in the media query.
:root {
--min-screen-height: 100px;
}
.App {
display: grid;
grid-template-columns: 0.7fr 0.9fr 1.5fr 0.9fr;
grid-template-rows: 2.75rem 3fr;
grid-template-areas: 'nav nav nav nav' 'sidebar leftmenu content rightmenu';
gap: 0.75rem 0.4rem;
}
.navigation {
grid-area: nav;
background-color: yellow;
}
.sidebar {
min-height: var(--min-screen-height);
grid-area: sidebar;
background-color: aliceblue;
}
.leftmenu {
grid-area: leftmenu;
background-color: skyblue;
}
.content {
min-height: var(--min-screen-height);
grid-area: content;
background-color: blanchedalmond;
padding: 0.5em 0.75em 0.5em 0.75em;
}
.rightmenu {
grid-area: rightmenu;
background-color: coral;
}
#media screen and (max-width: 768px) {
.App {
grid-template-columns: 1fr;
grid-template-areas: 'nav' 'content';
}
.sidebar,
.rightmenu,
.leftmenu {
display: none;
}
}
<div class="App">
<div class="navigation">Nav</div>
<div class="sidebar">Side bar</div>
<div class="leftmenu">Left Menu</div>
<main class="content">Main</main>
<div class="rightmenu">Right Menu</div>
</div>

Related

CSS Grid layout with dynamic height

I need to create layout 2x2 blocks with min-width 500px and min-height 300px. (first img).
I can collapse blue block (by click on it) to height 100px and the block which is below must fill the gap and become bigger. The same behaviour if lower block collapsed, the upper will stretch. (second img)
if screen width > 1200, turn it into 4 columns with width:300px, height:600px (third img) enter image description here
I tried to do add for parent
width: 100%;
height: 100%;
display: grid;
grid-template-rows: minmax(300px, 1fr) minmax(300px, 1fr);
grid-template-columns: minmax(500px, 1fr) minmax(500px, 1fr);
grid-column-gap: 25px;
grid-row-gap: 25px;
}
and also added
#media (min-width: 1200px) {
.parent {
grid-template-rows: minmax(600px, 1fr);
grid-template-columns: repeat(4, minmax(300px, 1fr));
}
}
but I don't know how to implement collapsing
Try this. I use the columns property on the parent to make a 2 column layout with the children to be flex containers. This means that when the flex children are clicked, we can use flex-grow, flex-shrink and flex-basis to make the clicked one smaller and the unclicked one automatically grow.
For screen sizes greater than 1200px, I've used a media query to flip the flex container to flex-direction: row which makes your four columns. The only bit that's annoying is that the column layout, the middle section is wider than the other parts. You might be able to fix this with a bit of tweaking
window.onload = () => {
document.querySelector('.container').addEventListener('click', (e) => {
e.target.classList.toggle('shrink');
});
}
.container {
columns: 2;
padding: 0.5rem;
border: 3px solid black;
height: 600px;
}
.column {
display: flex;
flex-direction: column;
height: 100%;
}
[id^="b"] {
background-color: #00A8F3;
border: 3px solid black;
margin-bottom: 0.5rem;
display: grid;
place-items: center;
padding: 1rem;
flex-grow: 1;
flex-shrink: 1;
}
.shrink {
flex-basis: 100px;
flex-grow: 0;
}
#media screen and (min-width: 1200px) {
.column {
flex: 1;
flex-direction: row;
justify-content: space-evenly;
}
.container {
display: flex;
}
[id^="b"] {
flex-basis: 300px;
flex-grow: 0;
flex-shrink: 0;
}
}
<div class='container'>
<div class='column'>
<div id='b1'>1</div>
<div id='b2'>2</div>
</div>
<div class='column'>
<div id='b3'>3</div>
<div id='b4'>4</div>
</div>
</div>
You can try like below. I added a checkbox to simulate the switch between (1) and (2)
.container {
display: grid;
grid-template-columns: 1fr 1fr; /* 2 columns */
grid-auto-flow: dense;
gap: 20px;
border:1px solid;
height: 300px;
}
.container > div {
display: flex;
flex-direction: column;
gap: 20px;
}
.container > div > div {
flex-grow: 1; /* fill remaining height */
height: 100%; /* we start with equal div */
background: lightblue;
font-size: 20px;
}
#media (max-width: 1200px) {
/* update the height on toggle */
input:checked ~ .container > div:first-child > div:last-child,
input:checked ~ .container > div:last-child > div:first-child {
height: 80px;
}
}
#media (min-width: 1200px) {
.container {
grid-template-columns: 1fr 1fr 1fr 1fr; /* 4 columns */
}
.container > div {
display: contents; /* remove inner divs */
}
/* rectify the order */
.container > div:first-child > div:last-child {
grid-column: 3;
}
}
<input type="checkbox">
<div class="container">
<div>
<div> 1 </div>
<div> 3 </div>
</div>
<div>
<div> 2 </div>
<div> 4 </div>
</div>
</div>

how can i make dynamic layout using media query?

I've been trying to make a few layouts for specific sizes.
As shown in the picture above, I tried to create two layouts, PC and mobile.
Making a PC was easy. SectionA and SectionB were configured through the flex layout, and SectionC was configured below it.
The problem was with Mobile. SectionA and SectionB are tied together in a flex layout, so I couldn't think of a way to put SectionC between A and B.
This is because, in the html structure, sectionC already exists below. Is it possible to configure only with CSS without using Javascript?
.header {
display: flex;
flex-direction: row;
justify-content: space-between;
/*only for ilustration*/
background-color: #d7d7d7;
}
.bottom {
display: flex;
flex-direction: row;
/*only for ilustration*/
background-color: #ffd5d5;
}
#media screen and (max-width: 760px) {
.header {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.bottom {
flex-direction: column;
border: none;
}
}
<div>
<div class="header">
<div>
SectionA
</div>
<div>
SectionB
</div>
</div>
<div class="bottom">
SectionC
</div>
</div>
I have just made a change in your HTML.
So I wrapped all div inside of .header.
Then, to give 50% width for first to direct child I have just added class .hlalf and set this class CSS to flex:1 0 50%, which means take 50% width of flexbox.
Now to achieve bottom div in center in responsive we use order property of flexbox. and for that I have just added class to all 3 div according to their order. I have used sm keyword just for understanding as small screens.
#media screen and (max-width: 560px) {
.order-sm-1 {
order: 1;
}
.order-sm-2 {
order: 2;
}
.order-sm-3 {
order: 3;
}
}
.header {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.header>div {
flex: 1;
}
.header>div.half {
/*This css tells all the direct div of header class to take 50% of the space*/
flex: 1 0 50%;
}
.bggreen {
background: green;
}
.bgblue {
background: blue;
}
.bottom {
background-color: #ffd5d5;
}
#media screen and (max-width: 760px) {
/*This will change flex-direction to column which is by default row*/
.header {
flex-direction: column;
}
.order-sm-1 {
order: 1;
}
.order-sm-2 {
order: 2;
}
.order-sm-3 {
order: 3;
}
}
<div>
<div class="header">
<div class="bggreen half order-sm-1">
SectionA
</div>
<div class="bgblue half order-sm-3">
SectionB
</div>
<div class="bottom order-sm-2">
SectionC
</div>
</div>
You can wrap all your section in a flex container and play with the flex-order properties
I'm late to the party with this one but Grid's the way to go in my opinion as you get complete control over where you put items. It's much more versatile than flexbox but it is a steep learning curve initially as there are so many options. Kevin Powell has a good introductory video to grid and this is also a good, clearly-written resource from css tricks.
.container {
display: grid;
grid-template-columns: 3fr 1fr;
grid-template-areas: "a b" "c c";
border: 2px solid #285DBB;
row-gap: 0.25rem;
column-gap: 2rem;
padding: 0.35rem;
}
.container>div {
background-color: #92D050;
color: white;
display: grid;
place-content: center;
padding: 0.75rem 2rem;
}
.zoneA {
grid-area: a;
text-decoration: underline wavy red;
}
.zoneB {
grid-area: b;
}
.zoneC {
grid-area: c;
}
.footer {
margin-top: 1.5rem;
font-size: 1.25rem;
text-align: center;
}
.mobile {
display: none;
}
.pc {
display: block;
}
#media only screen and (max-width:760px) {
.container {
grid-template-columns: 1fr;
grid-template-rows: 1fr 3fr 1fr;
grid-template-areas: "a" "c" "b";
}
.mobile {
display: block;
}
.pc {
display: none;
}
.zoneB {
text-decoration: underline wavy red;
}
.zoneC {
text-decoration: underline wavy red;
}
}
<div class="container">
<div class="zoneA">
SectionA
</div>
<div class="zoneB">
SectionB
</div>
<div class="zoneC">
SectionC
</div>
</div>
<div class="pc footer">PC</div>
<div class="mobile footer">Mobile</div>
<meta content="width=device-width,height=device-height,inital-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"/>

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.

Responsive design with CSS Grids

I'd like to have responsive version to this code.
body {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
"navigation-bar content content content";
margin: 0; padding: 0;
}
.navigation-bar {
grid-area: navigation-bar;
height: 100vh;
background-color: #1a1b20;
}
.content {
grid-area: content;
background-color: #202127;
}
<body>
<div class="navigation-bar"></div>
<div class="content"></div>
</body>
What I have:
#media only screen and (max-width: 600px) {
body {
}
.navigation-bar {
}
.content {
}
}
I'd like to have navigation-bar on the top of the website and content below it.
It means:
grid-template-columns should be 1fr
height of navigation-bar should be about 25vh
But I don't know, what grid-template-rows should be.
It depends on content, but if there is no content in content, it should fill whole screen (navigation-bar and content is a rest).
May you help me with responsive desige, please?
EDIT:
On mobile phone:
I would write the base styles using columnar flex and then a use grid when the screen is larger than 600px. Note that in mobile, .content uses flex-grow: 1, which means it will fill all the remaining vertical space.
.navigation-bar {
height: 15vh;
background-color: #1a1b20;
}
.content {
flex-grow: 1;
background-color: #202127;
}
body {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
color: white;
}
#media only screen and (min-width: 600px) {
body {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-areas:
"navigation-bar content content content";
}
.navigation-bar {
grid-area: navigation-bar;
height: 100vh;
}
.content {
grid-area: content;
}
}
<div class="navigation-bar">navbar</div>
<div class="content">content</div>
jsFiddle

Change order of containers in mobile

I am using w3.css, want to change order of containers when on mobile ( check screenshot below). Is there any class in w3.css which help changing order of blocks? I don't want to use standard css flex, just wanted to use w3.css
Since you have the flexbox tag I'm giving you the Flexbox solution:
body {
color: #fff;
}
.parent {
display: flex; /* displays the children inline */
}
.child {
flex: 1; /* children take as much horizontal space as they can */
height: 100px;
}
.A {
background: blue;
}
.B {
background: red;
}
#media screen and (max-width: 568px) { /* adjust to your needs */
.parent {
flex-direction: column; /* stacks the children vertically */
}
.A {
order: 2; /* changes the order, i.e. displays the .A below the .B */
}
}
<div class="parent">
<div class="child A">A</div>
<div class="child B">B</div>
</div>
You can also do it with the Grid:
body {
color: #fff;
}
.parent {
display: grid;
grid-template-columns: repeat(2, 1fr); /* could also use: 1fr 1fr or 50% 50% without the repeat() */
grid-template-rows: repeat(2, minmax(100px, auto)); /* minimum height 100px, maximum height unlimited, adjust to your needs, you can also remove it, not mandatory */
}
.A {
background: blue;
}
.B {
background: red;
}
#media screen and (max-width: 568px) {
.parent {
grid-template-columns: 1fr; /* could also use: 100% */
}
.A {
order: 2;
}
}
<div class="parent">
<div class="A">A</div>
<div class="B">B</div>
</div>

Resources