Bootstrap Scroll Spy with Sticky Navbar not working as expected
Asked Answered
H

1

10

I'm having a problem with Bootstrap Scrollspy component.

I'm using a sticky-top navbar and when the nav button is clicked it scrolls to the correct element;

But the problem is that the sticky navbar is overlaying this element.

I tried using data-offset = "50" in the body tag but it affected nothing.

The body tag:

<body data-spy="scroll" data-target="#sectionsNav" data-offset="50">

The body tag css:

body {
  position: relative;
  overflow-y: auto;
}

The navbar:

<nav class="navbar navbar-light bg-light sticky-top">
        <div id="sectionsNav">
            <ul class="nav nav-pills text-center">
                <li class="nav-item">
                    <a class="nav-link" href="#wihe">What is Home Eats</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#hiw">How it Works</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#pws">Problems we Solve</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#jhen">Join Now!</a>
                </li>
            </ul>
        </div>
    </nav>

How it works div:

..
<div id="hiw" class="container">
...
..
.
</div>
..

Expected Behavior on clicking How it works button in the nav:

Expected Behaviour image

Occurring Behaviour:

Occurring Behaviour image Note That: The navbar is above How it Works header.

Edit

After applying @SMAKSS answer the scroll worked as charm. But another problem occured, in the navbar the highlighted element becomes the previous element.

At the following screenshot I pressed on How it Works and it scrolled correctly, But the highlighted navbar element is What is home eats which is the previous one. Incorrect highlighting i.e. If I clicked on Problems we Solve, How it Works becomes selected. It always select the previous one.

Edit Solution

I fixed the second problem by doubling the data-offset attribute to be 100. the code now looks like this:

<head>
 <style>
    html {
    scroll-padding-top: 70px;
    }

    body {
    position: relative;
    overflow-y: auto;
    }
 </style>
</head>

<body data-spy="scroll" data-target="#sectionsNav" data-offset="100">
...
.
</body>

Headon answered 9/5, 2020 at 2:9 Comment(1)
I got the best results with the same values for scroll-padding-top: 60px and data-offset="60".Fieldwork
S
10

The problem here happens when an element with position fixed comes into play. Although we still jump to the desired id, it won't recognise that we have a fixed position element. So it will ignore its height and jump wherever the element with a specific id matches the window top element.

To solve this, you need to add padding to your scroll jumps, like below:

html {
  scroll-padding-top: 70px; /* height of sticky header */
}

Learn more about scroll-padding in CSS-Tricks.

UPDATE

As we have gone further on this solution, the spying behaviour crashed since the scroll spy will only know whether we are in a section with a specific ID. So to fix this, there are several approaches like adding padding to each section according to navbar height or, as @Raamyy suggested approach, we can define data-offset on our body tag, respecting the height of the fixed navbar. You can read bootstrap scrollspy options for more information about data-offset.

Scrappy answered 9/5, 2020 at 2:18 Comment(3)
@Headon So this behavior happens because you are still in the previous section and didn't enter the how it works section, to fix this there are several approaches. One can be apply padding in each section. So if you want to apply such a thing you should apply the navbar height as the top padding of your section. If you can share your section codes, I can help with that.Scrappy
I doubled the data-offset from 50 to 100 and it worked as expected. I will edit the original post and add this solution. Thanks again!Headon
spent hours on this, and dozens of other stackoverflow answers couldn't do it. this answer finally worked for meOpposition

© 2022 - 2024 — McMap. All rights reserved.