One of the main selling points of the CSS grid is that it eliminates container DIVs.
But I found a very common layout in which this doesn't appear to be true.
This page is supposed to have 4 areas: header, side, main and footer. But notice that side and main have a different background, so how is this possible to achieve with CSS grid without creating a container element for side and main, and turning the grid into header, side+main, footer?
You need to think of this in terms of a 4-column grid...then assign your divs to the appropriate rows & columns.
The background can be managed by a pseudo-element on the body although I prefer a page containing div. Same effect.
Codepen Demo
Nore info: Breaking Out With CSS Grid Layout
.page {
display: grid;
min-height: 100vh;
grid-template-columns: 1fr 100px 300px 1fr;
grid-template-rows: min-content 1fr min-content;
grid-gap: .5em;
}
.page::before {
content: "";
grid-column: 1 / 5;
grid-row: 2 / 3;
z-index: -2;
background: pink;
}
header {
background: red;
padding: 1em 0
}
footer {
background: blue;
padding: 1em 0;
}
aside {
background: green;
}
main {
background: rebeccapurple;
}
header,
footer {
grid-column: 2 / 4;
}
aside {
grid-column: 2 / 3;
grid-row: 2;
}
main {
grid-column: 3 / 4;
grid-row: 2;
}
<div class="page">
<header>HEADER-CONTENT</header>
<aside></aside>
<main></main>
<footer>FOOTER CONTENT</footer>
</div>
In this case I substituted different widths for demo purposes...
grid-template-columns: 1fr 100px 300px 1fr;
for say
grid-template-columns: 1fr 300px 640px 1fr;
Where the total of 300px + 640px equates to your 940px "container" width. These can be adjusted as you prefer.
Related
When i use the responsive tool of Chrome(<699pw) it create a huge gap between the footer and the div base but i want the footer a the bottom of the page. I don't know if it is the grid of the parent . I want to extend the base and make it closed to the footer so even if we extend the responsive tool. So it'has to follow the footer
header {
display: grid;
grid-template: auto;
grid-template-columns: 1fr 5fr 6fr 4fr;
align-items: center;
font-size: 30px;
position: relative;
top: 50%;
}
.parent {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-column-gap: 0px;
grid-row-gap: 0px;
}
.div1 { grid-area: 1 / 1 / 2 / 2; }
.div2 { grid-area: 1 / 2 / 2 / 3; }
.div3 { grid-area: 2 / 1 / 3 / 2; }
.div4 { grid-area: 2 / 2 / 3 / 3; }
.div5 { grid-area: 3 / 1 / 4 / 3; }
#bases{
display: grid;
grid-template: auto;
grid-template-columns: 2fr 4fr;
}
html,body{
margin: 0;
padding: 0;
}
/* Responsive */
#media (max-width: 699px){
#Titre {
display: none;
}
header {
background-color: #aa1010;
font-family: 'LexendTera';
color: white;
display: grid;
grid-template: auto;
grid-template-columns: 1fr 5fr 6fr 4fr;
align-items: center;
font-size: 10px;
position: relative;
top: 50%;
}
aside{
display: none;
}
#bases{
display: grid;
grid-template-columns: 1fr;
}
.parent{
display: grid;
align-items: center;
}
/* Mettre footer en bas de page */
footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
}
<!DOCTYPE html>
<html lang="fr">
<body>
<header>
<img src="img/logo.png" alt="logo" id="logo">
<h1 id="Titre">O'kebab</h1>
Composition
Connexion
</header>
<div id="bases">
<main>
<h1>"La maison du sandwich"</h1>
<div class="parent">
<div class="div1"><h1>Promotion</h1><p>Kebab Végetarien -50%</p> </div>
<div class="div2"><img src="img/vege.png" alt="vege"></div>
<div class="div3"><h1>Kebab du mois</h1><br><p> Kebab spicy</p></div>
<div class="div4"><img src="img/spicy.webp" alt="spicy"></div>
<div class="div5"><button>Commandez</button></div>
</div>
</main>
</div>
<footer>
<h2 id="contact">Contact</h2>
<h2 id="mention">Mentions légales</h2>
<img src="img/facebook.png" alt="facebook" id="face">
<img src="img/instagram.png" alt="instagram" id="insta">
<img src="img/iutly.png" alt="twitter" id="ly1">
<h3 id="tkt">© 2022 O'kebab</h3>
</footer>
</body>
</html>
I tried to use position:relative for the body but nothing change
The grid is fine,
In the screen size less than 699px width:
You made the header smaller by reducing its font size. And since a div is a block element by default, it would be positioned in a new line after the last element. So your "bases" div would be on top and attached beneath the header.
You forced the footer to be positioned fixed and go to the bottom of the page.
So naturally, there would be a gap between your "bases" and your "footer".
Now since the element positioned fixed is removed from the normal document flow, and no space is created for it on the page, you can't position the "bases" div relative to the "footer".
But, for fixing the gap between your divs there are many ways...
For example, you can add a height to your "bases" div and make it fill the gap.
If you want it to be responsive, instead of an absolute height you can give it a relative height, like using "%" or "vh":
#bases {
/* Relative to % of the height of the viewport */
height: 80vh;
}
And you can adjust the position of contents by "display flex" and "align-items" or maybe using padding and margins.
You can also make it "position absolute" as well and position it somewhere in the middle of the page. as I said there are many ways to fill that gap.
And a quick tip for using media queries, If you want to change an attribute of an element, you don't need to write all of its attributes again.
for example, if you have this code and you want to change its font size:
.header {
display: grid;
grid-template: auto;
grid-template-columns: 1fr 5fr 6fr 4fr;
align-items: center;
font-size: 30px;
position: relative;
top: 50%;
}
You can just change the font size, and there is no need to duplicate all of that code:
#media (max-width: 699px) {
.header {
font-size: 10px;
}
}
In the below snippet, I can not understand how .cell1(orange) height has been computed. Why it is so high? Why it is higher than right column content? How left cells height depends on right column and it's contains height?
header {
display: grid;
grid-template-columns: 70% 30%;
grid-template-rows: 62px auto;
background: beige;
}
.cell1 {
grid-column: 1/2;
grid-row: 1/2;
background: salmon;
}
.cell2 {
grid-column: 1/2;
grid-row: 2/3;
background: MediumSpringGreen;
}
.cell3 {
grid-row: 1/3;
grid-column: 2/3;
background: PeachPuff;
}
.cell3-1 {
background: MediumPurple;
height: 5px;
}
.cell3-2 {
background: LightSkyBlue;
height: 10px;
}
.cell3-3 {
background: Navy;
height: 30px;
}
<header>
<div class="cell1">1</div>
<div class="cell2">2</div>
<div class="cell3">
<div class="cell3-1"></div>
<div class="cell3-2"></div>
<div class="cell3-3"></div>
</div>
</header>
Let's start with your title.
How css grid computes row auto height?
auto just means it adapts to the height of the content within it. If the content in an auto row, is 100px tall, the row will be 100px tall.
I can not understand how .cell1(orange) height has been computed. Why it is so high?
Because you have told the first row to be 62px tall here:
grid-template-rows: 62px auto;
Why it is higher than right column content?
It isn't...but I can see that you might think that.
How left cells height depends on right column and it's contains height?
The right content in the context of the grid is only the .cell-3 div but you have told div to span 2 rows. So it assumes the combined height of .cell- and .cell-2.
The content inside cell-3 does not inherit any of the grid properties and so flows as normal.
I want to use percentages in my css for my react app but it's causing such a headache. Width % work fantastic all the time but the height % is always an issue. It seems almost like I HAVE to specify a height in pixels for it to work work unless the element contains children.
Am I missing something fundamental here. Will a div not set itself to 100% of the remaining height without child elements. The below code doesn't work despite me setting the align-items property to stretch.
.search-container{
display: grid;
grid-template-columns: auto 900px 300px auto;
grid-template-rows: 30% auto auto;
grid-gap: 20px;
}
.promo-container {
background-color:blue;
grid-column-start: 2;
grid-column-end: 3;
align-items: stretch;
}
.form-container {
background-color:blue;
grid-column-start: 3;
grid-column-end: 4;
align-items: stretch;
}
.results-header {
background-color:rgb(255, 94, 0);
grid-column-start: 2;
grid-column-end: 4;
height: 90px;
}
.refine-search {
background-color:blue;
grid-column-start: 2;
grid-column-end: 3;
height: 100%;
}
.results-container{
background-color:rgb(0, 255, 42);
grid-column-start: 2;
grid-column-end: 3;
}
<div className="search-container">
<div className="promo-container">
</div>
<div className="form-container">
</div>
<div className="results-header">
</div>
<div className="refine-search">
</div>
<div className="results-container">
</div>
</div>
You need to set the height of your parent elements.
html, body, div {
height: 100%;
width: 100%;
}
The problem with height is that you need to have some childrens in order to work. So if you want to see the blank space where is supposed to be the childrens ( the rest of the elements) you indeed have to set pixels, rem, fr, etc. Otherwise The grid won't allow the blank space to be there if there's nothing in there. For example if I want to see my remaining space I can say:
`.someClass {
display: grid;
/* I'm setting the rows to be 3 row with a given space of 1 fr
each row will be placed with given space unit */
grid-templates-rows: repeat(3, 1fr);
grid-template-columns: repeat(5, 1fr);
}`
Otherwise if you want to create the grid depending automatically on the availaible space you can set everything to auto like so:
.someotherClass {
display: grid;
/* grid template areas is the combination of the template rows and columns */
grid-templates-areas: auto;
}
Of course with the auto I can still order my items on the rows and columns that I want but the space will be adjusted accordingly with each element
To give you some idea how the grid works check out this page: https://cssgridgarden.com/
Hope helps :)
* {
/* CSS Reset! */
margin: 0;
/* They cascade, so for them to be accessible in
the sidebar div, you have to make them available for all */
--SideBarButtonSide: 36px;
--SideBarOffsetX: 16px;
--SideBarOffsetY: 17px;
}
#SideBar {
position: fixed;
top: calc(2*var(--SideBarOffsetY) + var(--SideBarButtonSide));
}
#SideBar #SideBarGrid {
display: grid;
--SideBarTextHeight: 45px;
grid-template-columns: 1fr 250px 1fr;
grid-template-rows: 40px 200px 20px var(--SideBarTextHeight) 20px 200px;
}
#SideBarGrid #BrandLogo {
grid-column: 2 / 3;
grid-row: 2 / 3;
margin: auto;
}
#SideBarGrid #SideBarText {
grid-column: 2 / 3;
grid-row: 4 / 5;
text-align: center;
line-height: var(--SideBarTextHeight);
font-size: 35px;
}
#SideBarGrid #SideBarLinks {
/* 1 / 2 and 3 / 4 work just fine! but try 2 / 3! */
grid-column: 2 / 3;
grid-row: 6 / 7;
}
https://codepen.io/Whiteclaws/live/vpbRXL
https://imgur.com/a/fAHVd
This problem is a bit hard to put into words, so please just have a look at the codepen for yourself...
The small codepen and imgur gallery describes the issues pretty well.... You can switch to position: relative and it'll work just fine! but that would defy the point of a sidebar...
Note: One more thing, it breaks at three elements, if i only put in two (brand logo and sidebar text, it works fine!!)
Note2: It breaks even without the links, for that matter, just having the SideBarLinks div inside breaks it!
Try to change grid-template-columns: 1fr 250px 1fr; to grid-template-columns: 1fr 1fr 250px;. That is what you want?
I'm trying to make a grid column span every row, including implicit rows.
I came across this question asking how to span all grid rows. The second answer has a correction stating a better solution. This seems like it would work, but my own example, and the comments on the second answer, indicate that it doesn't work.
The W3 spec gives this a very close example as well.
Is there something wrong with my code, or is this possibly a bug in Firefox, Chrome, and Safari?
I also have this example in a CodePen here.
* {
box-sizing: border-box;
}
.container {
border: 1px solid #666;
max-width: 1000px;
padding: 10px;
display: grid;
grid-template-columns: 150px 1fr 300px;
/* grid-template-rows: repeat(auto) [rows-end]; Doesn't seem to help */
/* grid-template-rows: [rows-start] repeat(auto) [rows-end]; Doesn't seem to help */
grid-template-rows: repeat(auto);
grid-gap: 10px;
margin: 10px auto;
grid-auto-flow: row dense;
/* justify-items: stretch; */
/* align-items: stretch; */
}
.container>* {
grid-column: 2 / 3;
padding: 10px;
outline: 1px solid #666;
}
.pop {
grid-column: 1 / 2;
/* grid-column: 1 / -1; If I switch to this, this div will span the full width of the grid, which is exactly what I'm trying to do with rows*/
}
.tertiary {
grid-column: 1 / 2;
}
.secondary {
grid-column: 3 / 3;
grid-row: 1 / -1;
/* Doesn't work */
/* grid-row: rows-start / rows-end; Doesn't work */
/* grid-row: 1 / rows-end; Also doesn't work */
/* grid-row: 1 / span 7; This works, but I need to span an unknown number of rows*/
/* grid-row: 1 / span 99; This is gross and creates 99 rows */
}
<div class="container">
<div class="secondary">Secondary - why doesn't this span all the way to the bottom of the grid?</div>
<div class="tertiary">Tertiary</div>
<div class="tertiary">Tertiary</div>
<div class="tertiary">Tertiary</div>
<div>Primary</div>
<div>Primary</div>
<div>Primary</div>
<div class="pop">Span tertiary and primary</div>
<div>Primary</div>
<div class="tertiary">Tertiary</div>
<div>Primary</div>
<div>Primary</div>
</div>
There are two obstacles in your way.
First, this line of CSS code in your .container rule:
grid-template-rows: repeat(auto);
This code is invalid. The argument in the repeat() notation must begin with a positive integer, which specifies the number of repetitions. You don't have that, so the code doesn't work. More details in the spec.
Second, even if the code above was correct, let's say:
grid-auto-rows: auto; (which happens to be the default setting anyway)
Your column would still not span all rows.
This is because, as you may have seen in the other answer you cited, a track definition can be set to cover all perpendicular tracks only in the explicit grid.
So this would work:
grid-template-rows: repeat(6, auto);
revised demo
The rest of the problem is covered in detail in the other answer you cited.