How to make the div 100vh even if it has no children? - html

I have a simple page, which consists of a header, body, and footer. During the development, I want the content to have as much height as possible so that the entire page will have 100vh. The problem is that if I only put some plain text content as the body(so no children tags for the body), it will look like this:
It's wrong because then I will have to add height: 100%; width: 100%; in every children's style to make use of the full height of its parent. (imaging I pass a <div className=...>...</div> as the children)
This is the page.tsx:
import Footer from '#/components/Page/Footer'
import Header from '#/components/Page/Header'
import styles from './index.module.css'
interface PageProps {
children: any
}
function Page({ children }: PageProps) {
return (
<div className={styles.page}>
<Header />
{children}
<Footer />
</div>
)
}
export default Page
I already made .page:
.page {
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
}

Seems like you want the children content inside to grow and fill up all the available spaces within its display: flex parent, it will be a good time to use flex-grow property.
Try this:
import Footer from '#/components/Page/Footer'
import Header from '#/components/Page/Header'
import styles from './index.module.css'
interface PageProps {
children: any
}
function Page({ children }: PageProps) {
return (
<div className={styles.page}>
<Header />
<div className={styles.childrenContainer}>
{children}
</div>
<Footer />
</div>
)
}
export default Page
.page {
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
}
.childrenContainer{
flex-grow: 1;
}

One solution is to insert justify-content: space-between; on the page class, and margin-bottom:auto for your content to stick to your header.

Related

how to align flex items to represent a bar chart

I have been trying to style the react component so that it looks like a horizontal bar chart. However, I am unable to align the centre div to the left as expected.
here is my react component for each row.
import React from 'react'
const level3UnitItem = ({ item, ratio }) => {
return (
<div className='country-div' >
<div className='name-div'> <h1>{item.country}</h1></div>
<div style={{ width: `${ratio * 400}px`, backgroundColor: 'red' }} className='bar-div'>
</div>
<div className='number-div'><h1>{item.population.toLocaleString('en-US')}</h1></div>
</div>
)
}
export default level3UnitItem
here is the css
.country-div{
width: 100%;
display: flex;
justify-content: space-between;
padding: 1rem;
margin: .2px;
}
.country-div h1, h2{
font-size: small;
}
and the current design is
I am expecting it to be
You will have to put 'name-div' and 'bar-div' inside another div(a parent div), like this:
import React from 'react'
const level3UnitItem = ({ item, ratio }) => {
return (
<div className='country-div' >
<div className="name-bar-container">
<div className='name-div'> <h1>{item.country}</h1></div>
<div style={{ width: `${ratio * 400}px`, backgroundColor: 'red' }} className='bar-div'>
</div>
</div>
<div className='number-div'><h1>{item.population.toLocaleString('en-US')}</h1></div>
</div>
)
}
export default level3UnitItem
CSS for 'name-bar-container' div:
.name-bar-container {
width: 100%;
display: flex;
}
you can also add margin-left to 'bar-div' to format it.
Can you try this? i add div inside the center div. then style it..
import React from 'react'
const level3UnitItem = ({ item, ratio }) => {
return (
<div className='country-div' >
<div className='name-div'> <h1>{item.country}</h1></div>
<div class="__toLeft">
<div style={{ width: `${ratio * 400}px`, backgroundColor: 'red' }} className='bar-div'>
</div>
</div>
<div className='number-div'><h1>{item.population.toLocaleString('en-US')}</h1>
</div>
</div>
)
}
export default level3UnitItem
and as for the css
.country-div{
width: 100%;
display: flex;
justify-content: space-between;
padding: 1rem;
margin: .2px;
}
.country-div h1, h2{
font-size: small;
}
.__toLeft {
display: flex;
justify-content: flex-start;
align-items: center;
}
I figured a a way to align those elements by wrapping the last two div(inside parent-div) into a new div and that solve my porblem.
import React from 'react'
const level3UnitItem = ({ item, ratio }) => {
return (
<div className='country-div' >
<div className='name-div'> <h1>{item.country}</h1></div>
<div className='barbar-div'>
<div style={{ width: `${ratio * 400}px`, backgroundColor: '#ffa500 ' }} className='bar-div' >
</div>
<div className='number-div'><h1>{item.population.toLocaleString('en-US')}</h1></div>
</div>
</div>
)
}
export default level3UnitItem
.country-div{
width: 100%;
display: flex;
justify-content: space-between;
padding: .3rem;
margin: .2px;
/* border: 1px solid black;
border-radius: .25rem; */
line-height: 2;
}
.country-div h1, h2{
font-size: small;
}
.name-div{
width: 300px;
}
.barbar-div{
width: 100%;
display: flex;
justify-content: space-between;
}
1. Create a container element and set its display property to "flex" to make it a flex container.
2. Create the individual flex items that will represent the bars of the chart. These can be div elements or any other HTML elements you prefer.
3. Set the width of each flex item to the appropriate percentage based on the data you want to represent in the chart. For example, if you want to represent a 50% value, set the width of the flex item to 50%.
4. Set the height of each flex item to a fixed value, such as 20px, to create a consistent height for all the bars in the chart.
5. Use the align-items property on the flex container to align the bars vertically. For example, use "align-items: center" to center the bars vertically in the container.
6. Use the justify-content property on the flex container to align the bars horizontally. For example, use "justify-content: space-between" to distribute the bars evenly across the container.
7. Use CSS to add colors and other styling to the flex items to make them look like bars in a chart.
8. Finally, add labels and other text elements to the chart to provide context and information about the data.
Note: To make the chart responsive, you can use media queries to adjust the width and height of the flex items and container based on the screen size.

Make a div fill the height of the remaining screen space when header is fixed

In my site I have the following structure:
Header
Content
Footer
And I want to make the Header and the Footer size based on their content (not a fixed size). And the Content to fill the remaining space.
I saw many questions and answers like: Make a div fill the height of the remaining screen space
that solves similar cases but in my case, the Header and Footer sizes are unknown so I can't use the calc() function, and the Header Has position:fixed which removes it from the layout calculations and makes the
flex solutions of various kinds wrong:
html,
body {
height: 100%;
margin: 0;
}
.box {
display: flex;
flex-flow: column;
height: 100%;
}
.box .row {
border: 1px dotted grey;
}
.box .row.header {
flex: 0 1 auto;
position: fixed;
/* The above is shorthand for:
flex-grow: 0,
flex-shrink: 1,
flex-basis: auto
*/
}
.box .row.content {
flex: 1 1 auto;
}
.box .row.footer {
flex: 0 1 40px;
}
<!-- Source - https://stackoverflow.com/a/24979148-->
<div class="box">
<div class="row header">
<p><b>header</b>
<br />
<br />(sized to content)</p>
</div>
<div class="row content">
<p>
<b>content</b>
(fills remaining space)
</p>
</div>
<div class="row footer">
<p><b>footer</b> (fixed height)</p>
</div>
</div>
Or using this solution:
html,
body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
}
.header{
position:fixed;
}
.content {
flex-grow: 1;
border: 1px dotted red;
}
<!-- Source - https://stackoverflow.com/a/28771764-->
<body>
<div class="header">header</div>
<div class="content"></div>
</body>
Is there any way to do make the Content height = 100% - FooterHeight - HeaderHeight
When the Footer and Header dimensions are unknown, and the Header has fixed position?
Since the header is fixed, I think you would need to know its height through JavaScript, and set the body's min-height as 100% of the viewport's height minus the header's height. After, you could simply use CSS Grid on body, to have the content take all the avaiblable height. Like so:
document.body.style.minHeight=`calc(100vh - ${document.querySelector("header").clientHeight}px)`;
document.body.style.paddingTop= document.querySelector("header").clientHeight + "px";
body{
margin:0;
display:grid;
grid-template-rows:1fr auto;
}
header{
background:lightblue;
position:fixed;
top:0;
left:0;
width:100%;
}
div{
background:lightgreen;
}
footer{
background:lightyellow;
}
<header>I'm the header</header>
<div>I'm the content</div>
<footer>I'm the footer</footer>
I can think of two solutions based on the rather general description of your problem:
A) Use JavaScript to do the calculations for you and apply the values to margins or positions, whichever works better in your case;
B) You could repeat the contents of the header (and footer, id that's out of the document flow also) in element(s) atop the content and make it transparent and non-inter-active (pointer-events: none) - dirty, but if JS is not an option and your header does not offer some other way to determine it's height through some 'css-magic' it might be the only solution.
Quite often I find, that there are better solutions when the problem is more specifically described, so if you can tell us what elements make it impossible to know the height of the header, there might be better solutions. Often when ratios as with images are in play, vh can come to the rescue - even though tha can be tricky too...
Finally I found a pure css solution.
since the Header is in the top , using position: sticky instead of fixed will have the same result but the layout will take it into account when calculating:
html,
body {
height: 100%;
margin:0;
}
body {
display: flex;
flex-direction: column;
}
.header{
position:sticky;
}
.content {
flex-grow: 1;
border: 1px dotted red;
}
<!-- Source - https://stackoverflow.com/a/28771764-->
<body>
<div class="header">header</div>
<div class="content"></div>
</body>

How come my login block will not center in reactjs?

I am trying to get this block to center. Here is my code:
This is the CSS:
.login__body {
display: block;
text-align: center;
border: 1px solid lightgrey;
width: 400px;
height: 600px;
}
Here is the code:
import React from 'react';
import './App.css';
function LoginBody() {
return (
<div>
<div className="login__body">
<h1>Hello</h1>
</div>
</div>
);
}
export default LoginBody;
you can use display: flex to center the element within its parent!
function LoginBody() {
return (
<div className="login_container">
<div className="login__body">
<h1>Hello</h1>
</div>
</div>
);
}
and here at the css file
.login {
width: 100%;
height: 100vh;
position: relative;
&__container {
display: flex;
justify-content: 'center';
align-items: 'center'
}
&__body {
// ...
}
}
by doing this, your .login__container element with take the whole page and center its child(.login__body) in middle of it horizontally and vertically. you can find the documentation details for flex property here; also here is a more descriptive and easy article about flex from css tricks

how to have to sections that resize based on content and another that uses the remaining space

I'm trying to create a webapp screen where the header is stuck to the top and the footer stuck to the bottom all the time, and the main content is displayed inbetween with a scroll bar if necessary.
I want to make this possible in multiple devices, so the header and footer can change in height to fit the their content in smaller screens and the main content should use the remaining space.
Is is possible to create this behaviour with css? (maybe using flexbox?)
You are right - flexbox is perfect for this:
html,
body {
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
header {
background-color: #0800ff;
}
.content {
background-color: #fff;
flex-grow: 1;
overflow-y: auto;
}
footer {
background-color: #fec11a;
}
<section class="container">
<header>...</header>
<div class="content">
<ol>
<li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li>
</ol>
</div>
<footer>...</footer>
</section>
Notice how I use height: 100vh for the .container and flex-grow: 1 for the .content. That does the trick.

Make elements fill the remaining space

I have a simple HTML document. I have a header, a section and a div (that contains an unknown number of other divs).
The header and the section do not (and can not) have set heights. Their height comes from the content. Only their width is known (set to 100%).
Is it possible, with flexbox or other means, to get each of those child divs, in this case with class="fill" to be the height of the body - minus the header and section?
In other words, when someone goes to the page, I want them to see the header and the section and then have the first div.fill reach all the way to the bottom, forcing them to scroll to see the next div (but not scroll to see the bottom of the first child div).
I am using a templating system so unfortunately the structure of the HTML can not change and I would like to do this only in CSS.
<html>
<body>
<header> Header content, might contain an image</header>
<section> This is the sub header, unknown height </section>
<div class="container">
<div class="fill">I Want</div>
<div class="fill">Each of These</div>
<div class="fill">To be </div>
<div class="fill">The height of the body - the Header - the Section</div>
</div>
</body>
</html>
body {
display: flex;
flex-direction: column;
height: 100vh;
margin: 0;
}
.container {
flex: 1; /* 1 */
display: flex;
flex-direction: column;
overflow-y: scroll;
}
.fill { flex: 0 0 100%; } /* 2 */
header { background-color: aqua; }
section { background-color: orange; }
.fill:nth-child(odd) { background-color: yellow; }
.fill:nth-child(even) { background-color: lightgreen; }
<body>
<header> Header content, might contain an image</header>
<section> This is the sub header, unknown height </section>
<div class="container">
<div class="fill">I Want</div>
<div class="fill">Each of These</div>
<div class="fill">To be </div>
<div class="fill">The height of the body - the Header - the Section</div>
</div>
</body>
jsFiddle
Notes:
The flex-grow: 1 component of flex: 1 tells the .container element (a flex item child of body) to consume all remaining space. This will cause .container to use up any space not consumed by header and section.
The flex-basis: 100% component of flex: 0 0 100% tells the .fill items (flex item children of .container) to consume 100% height of the parent. So these items will always take the full height of flex-grow: 1 on the parent.
Because flex items are set, by default, to shrink in order to not overflow the container, an override is set with flex-shrink: 0 in the flex: 0 0 100% rule. This disables the shrinking feature and allows the items to stay fixed at 100% height. (Otherwise, regardless of the defined height / flex-basis, the items would shrink evenly to prevent an overflow. See demo.)
If you change the structure of the elements a bit you can get it with only css.
Basically add the first .fill element in a container with the header and the section (let's call it first). For the other divs use height: 100vh
body {
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
.fill {
height: 100vh;
overflow: auto;
}
.first {
flex: 1;
}
header { background-color: aqua; }
section { background-color: orange; }
.first, .fill:nth-child(odd) { background-color: yellow; }
.fill:nth-child(even) { background-color: lightgreen; }
<html>
<body>
<div class="container">
<header> Header content, might contain an image</header>
<section> This is the sub header, unknown height </section>
<div class="first">I Want</div>
</div>
<div class="fill">Each of These</div>
<div class="fill">To be </div>
<div class="fill">The height of the body - the Header - the Section</div>
</body>
</html>