'position: sticky' not working when 'height' is defined

I had the same issue, but I needed the height: 100%; on the parent container. In my case I have a sticky navigation, the content needs to grow to its full length and the footer should always be visible at the end of the page (but with no position attribute).

I fixed it by setting overflow: auto; to that parent container. Now the parent is still 100% tall but the sticky container inside it, doesn't matter the height limitations.


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?

What are `scrolling boxes`?

If you specify `bottom: 0` for position: sticky, why is it doing something different from the specs?