Sticky header disappearing after going a certain ways down the page
Asked Answered
C

3

10

I am building a website for my upcoming wedding and I want a sticky header, but for some reason, it "disappears" by moving up after you go a certain way down the page. My test url is this: https://betterradiotech.com. Here is the nav markup:

<!-- Start Nav -->
<header>
    <nav>
        <ul class="nav-list">
            <li><a href="/" title="Home">Home</a></li>
            <li><a href="/music/" title="Music">Music</a></li>
            <li><a href="/gallery/" title="Gallery">Gallery</a></li>
            <li><a href="/feed/" title="Feed">Feed</a></li>
        </ul>
    </nav>
</header> <!--/ End Nav -->

Here is the nav SCSS:

header {
    padding: 1em;
    position: sticky;
    top: 0;
    z-index: 100;
    width: 100%;
    background-color: $burgandy;
}
.nav-list {
    display: flex;
    flex-flow: row nowrap;
    li {
        list-style-type: none;
        margin-left: 10px;
    }
    a {
        color: $pink;
        font-weight: 600;
    }
}
.active-nav {color: $navy !important;}

There is no JavaScript in making the nav, except for making the active nav work...for completeness sake, I will include that as well:

switch(location.pathname) {
    case "/":
        document.querySelector("a[title*='Home']").classList.add("active-nav");
    break;
    case "/admin/":
        document.querySelector("a[title*='Admin']").classList.add("active-nav");
    break;
    case "/feed/":
        document.querySelector("a[title*='Feed']").classList.add("active-nav");
    break;
    case "/gallery/":
        document.querySelector("a[title*='Gallery']").classList.add("active-nav");
    break;
    case "/music/":
        document.querySelector("a[title*='Music']").classList.add("active-nav");
    break;
}

Why is my nav bar disappearing after a certain distance down the page? It seems to happen right before the end of the full background picture in the first section.

Clandestine answered 16/3, 2018 at 15:47 Comment(0)
B
9

I think you'll get the desired behavior by switching from sticky to fixed. Sticky is sort of a hybrid of fixed and relative positioning, and changes its behavior relative to context, and is commonly used to allow items to respond to its neighbors via scroll position.

Sticky positioning can be thought of as a hybrid of relative and fixed positioning. A stickily positioned element is treated as relatively positioned until it crosses a specified threshold, at which point it is treated as fixed until it reaches the boundary of its parent.

So you want:

header {
    position: fixed;
}

PS: The reason its disappearing for you is that your body has a computed height, but the contents of the body overflow beyond that height. The sticky element scrolls away once you scroll past the computed height of the body, which is the header's parent.

Blane answered 16/3, 2018 at 16:5 Comment(2)
Awesome, that worked!!! Thank you so much! One line changes are the best!Clandestine
Best wishes on the upcoming nuptials!Blane
D
22

The reason for this is probably that your containing element is not as tall as you think, and you may have to set that element's height to fit-content explicitly, because sticky elements cannot leave their parent!

In most situations, the simplest solution will be to add this rule to your CSS:

body {
  height: fit-content;
}

But generally, which solution you need and which element you have to apply it to depends on your document structure. Let's say it looks something like this:

<body>
  <header>
    <nav>
      <!-- Your navigation -->
    </nav>
  </header>
  <main>
    <!-- The main content of the site -->
  </main>
</body>

And you probably use some CSS reset that contains a rule like this one:

html, body {
  height: 100%;
}

This allows using percentage heights on your page, but it will break sticky headers without additional work.

When you look at the size of the body with the dev tools, everything may look alright:

MDN page on height property with html and body height at 100% scrolled all the way up.

But once you scroll down, you see a problem:

MDN page on height property with html and body height at 100% scrolled half way down, revealing the body element is too short.

The body is just as tall as your viewport. All other content you see is just overflowing out of it. But a sticky header can't do that, it will stay within the body and disappear with it. We now have three potential solutions:

If you don't need percentage-based heights on your page, you can use this CSS rule:

body {
  height: fit-content;
}

If there are some percentage-base heights, try replacing them with vh instead, and see if that works for you. Then you can apply the fix from above.

If you do need percentage-based heights, then you might want to make the body stay in place but scroll the overflowing content through it:

html {
  overflow: hidden;
}

body {
  overflow: scroll;
}
Dispensation answered 27/3, 2022 at 17:2 Comment(1)
Well Explained. Thank you for this answer. I am surprised the body with height 100% works this way. Never heard about itUnrighteous
B
9

I think you'll get the desired behavior by switching from sticky to fixed. Sticky is sort of a hybrid of fixed and relative positioning, and changes its behavior relative to context, and is commonly used to allow items to respond to its neighbors via scroll position.

Sticky positioning can be thought of as a hybrid of relative and fixed positioning. A stickily positioned element is treated as relatively positioned until it crosses a specified threshold, at which point it is treated as fixed until it reaches the boundary of its parent.

So you want:

header {
    position: fixed;
}

PS: The reason its disappearing for you is that your body has a computed height, but the contents of the body overflow beyond that height. The sticky element scrolls away once you scroll past the computed height of the body, which is the header's parent.

Blane answered 16/3, 2018 at 16:5 Comment(2)
Awesome, that worked!!! Thank you so much! One line changes are the best!Clandestine
Best wishes on the upcoming nuptials!Blane
D
0

The previous soultions did not work for my situation. position: fixed made the other elements hide beneath it. And adding margin top or top to them messed the header a little bit. After almost two days of banging my head against the wall, I ended up adding this css to my modal in my styles.scss:

.modal-class{
   display: initial;
}

This worked for me, hopefully helps save someone else's time.

Dietary answered 17/1, 2023 at 8:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.