Understanding auto in css grids [duplicate] - html

This question already has answers here:
Percentage Height HTML 5/CSS
(7 answers)
Closed 2 years ago.
I am pretty new to Web development and I am trying to learn CSS grids. While learning the CSS grid I tried to make one simple layout. It has one header section, one menu section, one sidebar section, and one footer section.
I used auto while defining grid template rows for the 2nd row, and gave conatiner height as 100%, so that 2nd row will stretch fully in the remaining space left by row 1 and 2.
But it didn't work that way, i am trying to figure out why 2nd row is not stretching vertically in the remaning space left.
Here is the conatiner css in which i defined the 2nd row as auto and conatiner height as 100%.
.container {
height: 100%;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 40px auto 40px;
}
fiddle link:
https://jsfiddle.net/791vtd4z/

That is because you did not give body a fixed height, yet you have .container a relative height: therefore, when the child .container simply stretches to its content height and not any further, since there's nothing absolute to compare against by using 100% (ask yourself: "100% of what?").
A solution will be to set .container { min-height: 100vh; } to fix that, which tells the element to at least be as tall as the viewport, and allow it to grow should the content inside menu or sidebar grow beyond what the viewport can contain.
* {
margin: 0;
top: 0;
bottom: 0;
font-family: sans-serif;
font-size: 1.2em;
}
title {
display: none;
}
.container {
min-height: 100vh;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 40px auto 40px;
}
.Header {
background-color: beige;
grid-column: 1/-1;
}
.Menu {
background-color: red;
}
.Sidebar {
background-color: burlywood;
grid-column: 2/-1;
}
.Footer {
background-color: aquamarine;
grid-column: 1/-1;
}
<div class="container">
<div class="Header">Header</div>
<div class="Menu">Menu</div>
<div class="Sidebar">Sidebar</div>
<div class="Footer">Footer</div>
</div>

To build on Terry's answer, you can achieve your desired result by giving body a height of 100vh, you could change the height of .container to 100vh, or you could give html and body a height of 100% (and keep the 100% height of .container).
This is because 100vh gives an element the full height of the viewport regardless of the height of its parents, while setting an element's full height using a percentage (i.e. 100%) means the element takes the full height of its parent, whatever that is. So an element with a height of 100% could still be zero, if its parent has no height.
To put this another way, when setting an element's height to 100% all of its parents need to be 100% as well for that element to take up the full viewport.
html, body{
height: 100%;
}
* {
margin: 0;
top: 0;
bottom: 0;
font-family: sans-serif;
font-size: 1.2em;
}
title {
display: none;
}
.container {
height: 100%;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 40px auto 40px;
}
.Header {
background-color: beige;
grid-column: 1/-1;
}
.Menu {
background-color: red;
}
.Sidebar {
background-color: burlywood;
grid-column: 2/-1;
}
.Footer {
background-color: aquamarine;
grid-column: 1/-1;
}
<div class="container">
<div class="Header">Header</div>
<div class="Menu">Menu</div>
<div class="Sidebar">Sidebar</div>
<div class="Footer">Footer</div>
</div>

Related

div take all available height

I'm using the following HTML
<div className="App">
<div className="AppMenu">
Menu
</div>
<div className="AppContainer">
Test
</div>
</div>
and this CSS:
.App {
min-height: 100vh !important;
max-height: 100vh !important;
height: 100vh !important;
background-color: red;
}
.AppMenu {
background-color: blue;
position: sticky;
top: 0px;
width: 100%;
font-size: 1.3em;
}
.AppContainer {
background-color: green;
}
how can I set / calc AppContainer size to take all heigh => 100vh-(AppMenu height)
with CSS (or js) ?
You already using the full height of a screen with 100vh. There is no need to use a nuke like !important which nearly always just mask the issue instead of solving it. Also min-height: 100vh; + max-height: 100vh; can be considered as bad coding. In this case you want a definite height of 100vh which is done by height: 100vh;. So you having 3 lines of code where you actually only would need 1.
The issue that you get a scrollbar and the screen is overflowing is caused by the default body margin. The element will be 100vh tall and use the default body amrgin which will cause an document height of more then 100vh. Therefor simply reset the default body amrgin to 0 with: body { margin: 0; }
However with that soultion you will have a potencial overflow issue. So you should either set an overflow rule to the container or use min-height instead.
To have the the AppContainer fill the remaining height there are multiple ways to solve it. The easiest way to solve it would be the sue of a CSS-Grid with grid-template-rows: min-content auto;. That way, the Menu will take up as much space as needed and the remining height will be used be the AppContainer.
body {
margin: 0;
}
.App {
height: 100vh;
background-color: red;
display: grid;
grid-template-rows: min-content auto;
}
.AppMenu {
background-color: blue;
position: sticky;
top: 0px;
font-size: 1.3em;
}
.AppContainer {
background-color: green;
}
<div class="App">
<div class="AppMenu">
Menu
</div>
<div class="AppContainer">
Test
</div>
</div>
Last but not least. for HTML you have to use class not className which would be invalid HTML as this attribute doesnt exist.
These lines make no sense. This can be removed:
max-height: 100vh !important;
height: 100vh !important;
To stretch .AppContainer to the full free height, use rule flex: 1:
.AppContainer {
...
flex: 1;
}
And for the .App, set the flex rules. Like this:
.App {
...
display: flex;
flex-direction: column;
}
Flex has very good browser support.
Do you need such a result?
.App {
min-height: 100vh !important;
background-color: red;
display: flex;
flex-direction: column;
}
.AppMenu {
background-color: blue;
position: sticky;
top: 0px;
width: 100%;
font-size: 1.3em;
}
.AppContainer {
background-color: green;
flex: 1;
}
<div class="App">
<div class="AppMenu">
Menu
</div>
<div class="AppContainer">
Test
</div>
</div>

In Grid layout, make image fit the height of its containing cell [duplicate]

This question already has answers here:
Why does minmax(0, 1fr) work for long elements while 1fr doesn't?
(1 answer)
Prevent content from expanding grid items
(3 answers)
Closed 2 years ago.
I made a simple grid layout with a single column and 3 rows. The first and last act as header and footer respectively, while the main content should go in the second cell.
If the footer cell is empty, its height is the same as the header's, that is, the height calculated by the grid layout (which is what I want to keep). When I add an image inside the footer cell, the cell grows to the image's height. I don't know what CSS to use to keep the footer's initial height, and adapt the image's height to fit in.
I made a code pen here : https://codepen.io/mavromatika/pen/zYvGrZo
Here's my CSS :
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.contenant-presentation {
height: 100%;
display: grid;
grid-template-rows: 1fr 10fr 1fr;
}
.header {
grid-column: 1 / 4;
background-color: orange;
}
.main-content {
grid-column: 1 / 4;
background-color: darkturquoise;
}
.footer {
background-color: #ebebeb;
grid-column: 1 / 4;
}
.img-container {
height: 100%;
}
.img-container img {
height: 100%;
width: auto;
}
And my HTML (inside the body tag):
<div class="contenant-presentation">
<div class="header">Les loups</div>
<div class="main-content"></div>
<div class="footer">
<div class="img-container">
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi.ytimg.com%2Fvi%2FupL-45sHwko%2Fhqdefault.jpg&f=1&nofb=1">
</div>
</div>
</div>

css grid how to expand element take up remaining space or scroll if too large?

Goal is to build a page the expands the height of the main content to remaining height of page but not to exceed the visible area. Instead it should max out and start vertically scrolling instead.
Is this possible in css grid without using max-height: 80vh for example? I don't always know what the max-height should be. (.app-main is large content that should expand but be capped at remaining height and then start scrolling vertically.)
body {
display: grid;
grid-template-rows: auto 1fr auto;
grid-row-gap: 1em;
height: 100vh;
}
.app-main {
height: 1800px;
background-color: yellow;
overflow-y: auto;
}
<header>
<h1>Header</h1>
</header>
<section class="app-main">
<p>
my large content
</p>
</section>
<footer>
<h2>Footer</h2>
</footer>
Setting the height on the children of section will achieve what you want. For example:
body {
display: grid;
grid-template-rows: auto 1fr auto;
grid-row-gap: 1em;
height: 100vh;
}
.app-main {
height: 100%;
background-color: yellow;
overflow-y: auto;
}
.app-main p {
height: 1200px;
}

Prevent grid area from expanding causing whole page to scroll

I'm using the following grid layout:
grid-template-columns: 10em 1fr 10em;
grid-template-rows: 2em 1fr 2em;
To create a centered area that fills most of the screen while leaving some padding around it. Inside this 1fr x 1fr grid area is a pane div which contains an editor div which contains a content div.
The content div can be any height, and the editor div has overflow: scroll set. My problem is that instead of pane staying the same size and editor handling the overflow, pane grows and causes the whole page to scroll.
I can keep pane from growing by setting its overflow: scroll, but this causes the editor itself to scroll, rather than its content. This is unacceptable because the editor has buttons which must always be on screen.
Is there a way, within grid layout, to allow this functionality? I originally had it working with a flex layout, where the pane div was a single item within a 100% x 100% flexbox. I switched to grid to allow me to easily resize side-menus, so implementing this without grid is not preferable.
Also, multi-browser support would be amazing, but my target browser is Chrome.
Here's a jsfiddle with my reproducing my problem.
body, html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#site {
width: 100%;
height: 100%;
background-color: #000;
display: grid;
grid-template-rows: 10em 1fr 10em;
grid-template-columns: 2em 1fr 2em;
grid-template-areas:
'top top top'
'lpn mid rpn'
'bot bot bot';
}
#pane {
grid-area: mid;
height: 100%;
width: 100%;
background-color: #f0f;
}
#editor {
display: relative;
overflow: scroll;
}
#content {
height: 2000px;
}
<div id='site'>
<div id='pane'>
<div id='editor'>
<div id='content'>
</div>
</div>
</div>
</div>
min-width: auto / min-height: auto
Generally speaking, a grid item cannot be smaller than its content. The default minimum size of grid items is min-width: auto and min-height: auto.
This often causes grid items to overflow their grid areas or grid containers. It also prevents scrollbars from rendering on the items, since an overflow condition can't be triggered (the grid item just keeps expanding).
To override this default (and allow grid items to shrink past their content size) you can use min-width: 0, min-height: 0 or overflow with any value other than visible.
This behavior, with references to official documentation, is explained in this post:
Prevent content from expanding grid items
1fr
Another thing to note is that 1fr means minmax(auto, 1fr). This means, again, that the track to which it is applied cannot shrink below the content size (i.e., the min value in the minmax() function is auto, meaning content-based).
Therefore, to override this setting, use minmax(0, 1fr) instead of 1fr.
More details here: https://github.com/w3c/csswg-drafts/issues/1777
revised demo (tested in Chrome, Firefox and Edge)
body, html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#site {
width: 100%;
height: 100%;
background-color: #000;
display: grid;
/* grid-template-rows: 10em 1fr 10em; */
grid-template-rows: 10em minmax(0, 1fr) 10em; /* new */
grid-template-columns: 2em 1fr 2em;
grid-template-areas:
'top top top'
'lpn mid rpn'
'bot bot bot';
}
#pane {
grid-area: mid;
height: 100%;
width: 100%;
background-color: #f0f;
overflow: auto; /* new */
}
#editor {
/* display: relative; */
/* overflow: scroll; */
}
#content {
height: 2000px;
}
<div id='site'>
<div id='pane'>
<div id='editor'>
<div id='content'></div>
</div>
</div>
</div>
jsFiddle demo
Not 100% sure if this is what you're asking. I added a wrapper to content to make it scrollable, and set a vh height on it, which you could adjust.
#content-scroll {
height: 40vh;
overflow: scroll;
}
#content {
height: 2000px;
}
<div id='site'>
<div id='pane'>
<div id='editor'>
<div id='content-scroll'>
<div id='content'>
</div>
</div>
</div>
</div>
</div>
https://jsfiddle.net/16owL8x0/

Filling content background till it reaches footer

I have similar problem which can be found here. But i couldn't make it work or i didnt understand it fully.
My problem which im trying to resolve is - I want my content background to reach footer even if there isnt enough content to be displayed. I created a simple fiddle which can be found here. As you can see there isnt enough content to reach footer and there is this "blue" space between content and footer. I would like to make that space grey.
HTML :
<div class=blue>header here</div>
<p>LOGO here</p>
<div class="blue">navigation bar here</div>
<div class="content">
No content.
</div>
<div class="footer">footer is here</div>
CSS:
.blue {
color: #ffffff;
background-color: #294a70;
display: block;
float: none;
width: 400px;
margin: 0 auto;
text-align: center;
}
p {
text-align: center;
color: #ffffff;
}
.content {
background-color: #e6e6e6;
display: block;
float: none;
margin: 0 auto;
overflow:hidden;
width:400px;
margin-bottom:30px;
}
.footer {
color: #ffffff;
background-color: #294a70;
display: block;
float: none;
width: 400px;
margin: 0 auto;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height:30px;
}
body {
margin:0;
padding:0;
font-family: 'Open Sans', sans-serif;
line-height: 1.5;
font-size: 14px;
overflow-x:hidden;
background-image:url('http://www.planwallpaper.com/static/images/Alien_Ink_2560X1600_Abstract_Background_1.jpg');
min-height: 100%;
}
html {
position:relative;
min-height: 100%;
}
All help will be appreciated!
Use CSS3 calc() function
the trick is, if you know the height of header & footer, you can use this function with vh units, 100vh gives you screen height, just substract the height of hearder & footer from it.
E.g.
If header is 80px & Footer is 40px, i.e. total 120px, then use
.content{
min-height: calc(100vh - 120px);
}
The purpose of using min-height is if content is not present then atleast this height is applied, but if there is more content than screen then div is expanded to fit accordingly.
Updated JSFiddle:
https://jsfiddle.net/vj07e8g1/5/
You could try a flexbox layout instead:
HTML
<body>
<header></header>
<main class="content"></main>
<footer></footer>
</body>
CSS
body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main.content {
flex: 1;
}
Check out this codepen example: http://codepen.io/StefanBobrowski/pen/zZXXWy
You can add this to your content style:
min-height:400px;
It'll push the footer a little, but it'll do the work.
Hope this is what you're looking for.
The easiest contemporary way, depending on your browser-support requirements, would be to use CSS grids, which allows you to define rows and columns and assign certain content to be in specific places (placed by grid-row and grid-column), like follows:
html,
body {
height: 100%;
}
/* to force all elements to be sized including
their padding and border-widths */
body,
::before,
::after {
box-sizing: border-content;
}
body {
/* To use CSS grid, forcing the child elements of
the <body> element to adopt 'display: grid-item': */
display: grid;
/* defining the three columns of the grid, the first and
third being equal fractions of the space left over after
the second (middle) column's width of 400px is calculated */
grid-template-columns: 1fr 400px 1fr;
/* reducing the first three rows to the minimum height needed
to fully display their content, setting the fourth row
to take up the remaining unoccupied space once the other
heights are calcuated and setting the final row's height to
30px: */
grid-template-rows: min-content min-content min-content 1fr 30px;
height: 100vh;
background-image: url(https://i.stack.imgur.com/2oC8H.jpg);
}
body>* {
/* setting all the child elements of the <body> to be placed
in grid-column 2 (the central 400px-wide column): */
grid-column: 2;
}
/* Setting the default shared styles of the .blue elements: */
.blue {
color: #ffffff;
background-color: #294a70;
}
.blue.header {
/* positioning this element in the first (one-based counting)
row: */
grid-row: 1
}
body>p {
grid-row: 2;
}
.blue.navigation {
grid-row: 3;
}
div.content {
grid-row: 4;
/* background-color purely to show that the space of the
div.content element occupies the full space available: */
background-color: #ffa;
}
div.footer {
grid-row: 5;
}
<div class="header blue">header here</div>
<p>LOGO here</p>
<div class="blue navigation">navigation bar here</div>
<div class="content">
No content.
</div>
<div class="footer">footer is here</div>
JS Fiddle.
Please note that I did add a class-name to both the .blue elements in order to more-easily distinguish them according to their roles in the document, and from each other when placing them in the document.