I am building a landing page where the user first sees a main area with a footer underneath it. Scrolling further down reveals that the footer is a sticky header, and I aim to use pure CSS to achieve this. To obtain the fullscreen appearance of the main content and the footer I set the height
property to two different values: 92% and 8% (using vh
also doesn't work). No matter the height
I specify in my CSS (different units and all), my footer div
is not sticking. As soon as I remove the height
property it works as intended.
Here is a screenshot of my page before removing the height
properties:
As you can see, it does not stick:
After removing the height
property values, it does stick:
Below the relevant code:
I have read that using the overflow
property can be problematic, though it is is not present nor have I heard anything about height
being an issue for others. I might be wrong, of course.
I have tested on:
EDIT: Big development; removing the height
property from #main
keeps #footerNav
sticky.
The issue here is with height
, but not the height
you thought about. Let's first start by the definition of the sticky position:
A stickily positioned element is an element whose computed position value is sticky. It's treated as relatively positioned until its containing block crosses a specified threshold (such as setting top to value other than auto) within its flow root (or the container it scrolls within), at which point it is treated as "stuck" until meeting the opposite edge of its containing block.
The important part here is the last sentence which explain that the position sticky will end when the element reach the edge of its containing block and in your case the containing block of the sticky element is the body and you set the body to be height:100%
and you are having an overflow of content.
So when setting the height of main to be 92% and the footer to be 8%, you already made the footer at the oppsite edge of its containing block. Here is an illustration where I added a background color to the body so you can clearly see this:
html,
body {
height: 100%;
margin: 0;
}
html {
background:white;
}
body {
background:blue;
}
#main {
height: 92%;
}
#landing {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
text-align: center;
}
#landingContent {
width: 20vw;
}
#footerNav {
height: 8%;
display: flex;
align-items: center;
position: sticky;
top: 0px;
background:red;
color:#fff;
}
<div id="main">
<div id="landing">
<div id="landingContent">
<h1 class="logo">Logo</h1>
<p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
<button>Button</button>
</div>
</div>
</div>
<div id="footerNav">
<div id="footerNavContent">
<h1 class="logo">Logo</h1>
</div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
As you can see the logo is already at the bottom of the body so there is no way to make it move as sticky. Also your content is overflowing.
Now if you decrease the height of the main content a bit, you can see a small sticky behavior that will end when the footer will reach the bottom of the blue part (the body
).
html,
body {
height: 100%;
margin: 0;
}
html {
background:white;
}
body {
background:blue;
}
#main {
height: 82%;
}
#landing {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
text-align: center;
}
#landingContent {
width: 20vw;
}
#footerNav {
height: 8%;
display: flex;
align-items: center;
position: sticky;
top: 0px;
background:red;
color:#fff;
}
<div id="main">
<div id="landing">
<div id="landingContent">
<h1 class="logo">Logo</h1>
<p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
<button>Button</button>
</div>
</div>
</div>
<div id="footerNav">
<div id="footerNavContent">
<h1 class="logo">Logo</h1>
</div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
In order to fix the issue you simply need to avoid setting height:100%
to the body. You can use min-height
instead or keep its height auto. You may also consider vh
unit for main and footer:
html,
body {
/*height: 100%;
no needed
*/
margin: 0;
}
html {
background:white;
}
body {
background:blue;
}
#main {
height: 92vh;
}
#landing {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
text-align: center;
}
#landingContent {
width: 20vw;
}
#footerNav {
height: 8vh;
display: flex;
align-items: center;
position: sticky;
top: 0px;
background:red;
color:#fff;
}
<div id="main">
<div id="landing">
<div id="landingContent">
<h1 class="logo">Logo</h1>
<p id="landingParagraph">Lorem ipsum, paragraph content, etc etc.</p>
<button>Button</button>
</div>
</div>
</div>
<div id="footerNav">
<div id="footerNavContent">
<h1 class="logo">Logo</h1>
</div>
</div>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
Related questions for more details/examples:
Why element with position:sticky doesn't stick to the bottom of parent?
If you specify `bottom: 0` for position: sticky, why is it doing something different from the specs?