Footer stuck in middle only when there is little content - html

I know the title is a known 'issue'. However, I have tried many solutions, but none seem to work.
My footer is stuck on the bottom (phew) on almost all cases (when there is a lot of content, when I can scroll,..). Sadly, when there is barely any content, it just goes straight to the middle. I really have no clue why this is happening :( I am using Gatsbyjs for my website.
This is the global.css
html {
height: 100%;
}
main {
flex: 1 0 auto;
}
body {
display: flex;
flex-direction: column;
position: relative;
height: 100%;
margin: 0;
font-family: "Roboto", sans-serif;
color: whitesmoke;
background: radial-gradient(circle at center, #2b2b2b, #414141);
}
My footer.js component and it's css is:
css:
footer {
background-color: #2b2b2b;
position: relative;
font-size: smaller;
opacity: 0.98;
padding: 1rem;
width: 100%;
margin-top: auto;
}
html for footer:
const Footer = () => {
return (
<div>
<footer>
<p>©Copyright {currentYear} Humital - Made with ❤️</p>
</footer>
</div>
)
}
export default Footer
the main html comes from layout.js:
<div className={styles.flex}>
<NavBar />
<div className={styles.container}>
<main>{children}</main>
</div>
<Footer />
</div>
Which holds some css for the container:
.container {
display: flex;
flex-direction: column;
padding-top: 5rem;
padding-bottom: 1rem;
margin-left: 1rem;
line-height: 1rem;
flex: 1 0 auto;
position: relative;
}
.flex {
flex: 1;
}
Not sure why the footer won't go down when there is no content :( Any help is welcome! :)

I think you just need to add min-height: 100vh rule (and a flex-direction) to your .flex class:
.flex {
flex: 1;
min-height: 100vh;
flex-direction: column;
}
Because your .container has the flex: 1 0 auto will push the footer to the bottom.
Summarizing, you only need this rules to stick your footer to the bottom:
.flex {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.container {
flex: 1 0 auto;
}
.flex applies to the outer wrapper, which contains the Footer, the <main> and the <NavBar />.
.container applies to the <main> or the <main>'s wrapper. I think it's not needed to wrap the <main> with another <div>, you can apply the styles directly to the <main> tag, yet the approach to push the footer to the bottom is exactly the same.

Related

Sticking footer to bottom of page using flexbox and margin-top: auto; not working

I'm trying to get my footer to stick to the bottom of the page using margin-top: auto; but it doesn't have any effect.
I thought it might be because the parent has no height set but when setting height: 100vh it just shrinks the footer: https://i.imgur.com/FBXpT7U.png
I can't figure out why this isn't working.
HTML:
<body>
<div class="footer">
<p>Text here</p>
</div>
</body>
CSS:
body {
display: flex;
flex-direction: column;
flex: 1;
}
.footer {
background-color: #1F2937;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 100px;
margin-top: auto;
}
I'm working through a project on "The Odin Project". Here's the full code: codepen
In your CodePen, the empty gap below the footer is taken up by the padding: 700px on .testimonial-text. Removing it (or lowering it to a reasonable value) fixes the issue.
You need to set max-width instead of using padding:700px to get the desired style!
.testimonial-text {
/* padding:700px; */
max-width:500px;
...
}

Flex-grow takes up its own margin as well when scrolling is needed

I have a container, in my case the body and html tags are the containers. And then I have 3 divs in them and I want the last one to fill the remaining vertical space available while still having a margin.
The third div is generated dynamically so I can't predict what height it's gonna need. The problem is, if it grows too much and a scrollbar is required, the bottom-margin it used to have goes away too. If a scrollbar is NOT required and doesn't appear, the margin is still there and everything looks like I want it to.
I tried to draw what I meant as best as I could in the above image. The 1st case is what I want to happen all the time, regardless of whether there's a scrollbar or not. The 2nd picture is what actually happens, the blue div loses its bottom margin, despite having it set.
Here's my CSS for the html and body tags (they contain the 3 divs, including the blue one):
html,
body
{
width: 100%;
height:100%;
margin: 0px;
padding: 0px;
display: flex;
flex-direction:column;
align-items: center;
background: #494d5f ;
}
and here's my code for the 3rd div, the blue one:
.bottomDiv
{
display:flex;
flex-direction:column;
background: #a0d2eb ;
align-items: center;
width: 97%;
margin-bottom:1.5%;
flex: 1 1 auto;
padding-top:1%;
padding-bottom:1%;
}
Maybe I didn't clarify well enough but the 3rd div in my case, the blue one grows just like it should, fully obeying its margins UNTIL a scrollbar appears and is needed. No matter the amount of growth it has to do, it does it perfectly while respecting its margin. But if it has to grow "out of bounds" of the page so to say, as in, a scrollbar is needed to display all the webpage then its margin is simply gone. IF there is NO scrollbar, everything looks perfect.
Just change this line: body { height: 100%; } to: body { min-height: 100vh; }.
With that line the body will have a height of at least the screen height (100vh) but allows i proper overflow as it is allowed to eb alrger then the screen. As such the margins wont get removed.
html,
body {
width: 100%;
min-height: 100vh;
margin: 0px;
padding: 0px;
display: flex;
flex-direction: column;
align-items: center;
background: #494d5f;
}
.topDiv,
.midDiv {
width: 97%;
height: 50px;
}
.topDiv {
margin-top: 1.5%;
background-color: red;
}
.midDiv {
background-color: blue;
}
.bottomDiv {
display: flex;
flex-direction: column;
background: #a0d2eb;
align-items: center;
width: 97%;
margin-bottom: 1.5%;
flex: 1 1 auto;
padding-top: 1%;
padding-bottom: 1%;
}
#height:checked + label::after {
content: "";
display: block;
height: 150vh;
}
<div class="topDiv"></div>
<div class="midDiv"></div>
<div class="bottomDiv">
<input type="checkbox" id="height" name="height">
<label for="height">checkmark me to extend box height</label>
</div>
I've put an example, so you may try this approach:
body,
html {
margin: 0;
padding: 0;
}
#page {
display: flex;
flex-direction: column;
height: 100vh;
outline: 1px solid purple;
}
#header {
height: 30px;
outline: 1px solid red;
}
#middle {
flex-grow: 1;
/* height: 100vh; */
/* flex-direction: column; */
outline: 1px solid green;
}
#footer {
outline: 1px solid blue;
}
<div id="page">
<div id="header">...</div>
<div id="middle">...</div>
<div id="footer">...</div>
</div>
Try to remove #footer and see that #middle fills the entire screen till the end.
In addition if you need any margins so you have to modify the container like this: #page { ..., margin: 10px; height: calc(100vh - 20px); }

Why is the container for h1 is a lot bigger than it needs to be?

I've started learning flexbox recently and tried doing some exercises to practice but I got stuck because the container for h1 is a lot bigger than it needs to be, even if margin and padding are 0, and it makes the whole other page uncentered.
main {
display: flex;
justify-content: center;
background-color: #cacaca;
height: 100vh;
flex-flow: row wrap;
}
h1 {
margin: 0;
padding: 0;
}
#container {
margin-top: 100px;
}
<main>
<h1>Here are some nice pics</h1>
<div id="container"> ... </div>
</main>
It's because default value of align-items is stretch which makes all flex items to stretch to full height of their parent. if you give align-item: flex-start to use only required height.
main {
height: 100vh;
display: flex;
justify-content: center;
align-items: flex-start;
}
h1 {
background: red;
}
<main>
<h1>Here are some nice pics</h1>
<div id="container">Container</div>
</main>

3 rows, 100% height layout, with flexbox

I'd like to know: is it possible to build a 3 rows layout, 100% height, with flexbox?
<header> The header content goes here. </header>
<div class="content"> The main content goes here. </div>
<footer> The footer content goes here. </footer>
fixed-height header and footer, while content the liquid part.
I mean, something like this but without absolute positioning:
* {
margin: 0;
}
header {
position: absolute;
width: 100%;
height: 64px;
top: 0;
background: red;
}
footer {
position: absolute;
width: 100%;
height: 64px;
bottom: 0;
background: green;
}
.content {
position: absolute;
width: 100%;
top: 64px;
bottom: 64px;
background: blue;
}
<header>The header content goes here.</header>
<div class="content">The main content goes here.</div>
<footer>The footer content goes here.</footer>
http://jsfiddle.net/BMxzn/
body {
display: flex;
flex-direction: column;
height: 100vh;
}
.content {
flex: 1; /* this is the key; consumes all available height */
background: blue;
}
header {
height: 64px;
background: red;
}
footer {
height: 64px;
background: green;
}
* {
margin: 0;
}
<header>The header content goes here.</header>
<div class="content">The main content goes here.</div>
<footer>The footer content goes here.</footer>
I add my own accepted answer here, because it addresses other issues as well.
I noted that the usually suggested code has a problem with Android prior to 4.4.4. By better indagating > this and > this I found out that the problem is > this, even if Android is not mentioned on the affected browsers list. So, my solution was to add flex-shrink: 0 to the content:
body{
display: flex;
flex-direction: column;
height: 100%;
}
.main-content{
flex: 1 0 auto; // flex-shrink:0 > android 4.4.2 fix (and some other browsers too)
}
It's also good to assign some kind of flex property to header and footer. I noticed on Android 442 that otherwise the bg color was gone:
.main-header,
.main-footer{
flex: none; // or flex something.
}
Also please note that I'm using Autoprefixer. Otherwise, you should not use the shortcut on main-content (IE shit-fix):
.main-content{
flex-grow: 1;
flex-shrink:0;
flex-basis:auto;
}
Very similar to these question : this & this
You need only 3 lines of code:
display:flex;
flex-flow:column;
height:/* whatever height needed */
and then flex:1; to the container that needs to fill remaining space
* {
margin: 0;
}
body {
display: flex;
flex-flow: column;
height: 100vh;/* if you relay on flex, then vh is also understood */
}
body>* {
padding: 1em;
}
header {
background: red;
}
footer {
background: green;
}
.content {
flex: 1;
background: blue;
color: white;
/* optionnal if you want to keep footer at screen
overflow:auto; */
}
<header>The header <b>of any height</b> content goes here.</header>
<div class="content">The main content goes here.</div>
<footer>The footer <b>of any height</b> content goes here.</footer>
there is no need to set heights to footer or header , but you might add overflow:auto to the main container.

Footer which takes the rest of the remaining window height but at least a specified amount of px

I found several questions about but none of their solutions was working for me so here we go again.
Let's say I have this template of HTML
<html>
<div id="header">...</div>
<div id="contentA">...</div>
<div id="contentB">...</div>
<div id="footer">...</div>
</html>
The footer div should be at least 80px height, but if those 80px plus the height of all other 3 divs is not enough to fullfill the screen I want the footer to increase as much as the screen is filled with it below header, contentA and contentB.
BG-Color Solution
If you just want to let the remaining space have the same background-color as the footer (but not the body), you could add the footer bg-color to the html-tag:
html {
background-color: #footer_color;
}
body {
background-color: #body_color;
}
#footer {
min-height: 80px;
}
.
JS-Solution
If you have something more complex within your footer, you could use javascript/jquery to calculate the remaining space and set the footer to that height.
There is a similar question with a code example here: https://stackoverflow.com/a/14329340/3589841
.
Flexbox-Solution
If you only care about the latest browsers you can use the flexbox-box-model:
HTML:
<html>
<body>
<div id="flex_container">
<div id="header">...</div>
<div id="contentA">...</div>
<div id="contentB">...</div>
<div id="footer">...</div>
</div>
</body>
</html>
CSS:
html, body {
min-height: 100%;
}
#flex_container {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: flex-start;
}
#header {
flex: 0 1 auto;
}
#contentA {
flex: 0 1 auto;
}
#contentB {
flex: 0 1 auto;
}
#footer {
flex: 0 1 100%;
min-height: 80px;
}
I believe you're going for something like this, have a look http://jsfiddle.net/dusUK/
Using CSS, we create a class, which in this case is fullheight, and we apply the following:
.fullheight {
display: block;
position: relative;
background: red;
height: 100%;
}
We also then apply the following to html, body
html, body {
height: 100%;
min-height: 100%;
}