Bootstrap scrollspy and sticky navigation not working together

user2586473 picture user2586473 · Jul 16, 2013 · Viewed 8.8k times · Source

Having a bit of a problem here mixing two elements!

I'm sure you have seen the technique before. A sticky navbar that lives beneath the feature area which then sticks to the top of the page when the user scrolls down. As the user scrolls down the page the nav bar lights up the appropriate section and the user can jump around sections using the navbar too..

Testing site is here:

http://www.domaincreative.co.uk/dev/midasflo-test2

The scrollspy bootstrap element appears to work well on scrolling. However once you click an area the problems occur. Often it goes to the wrong section or highlights the wrong area in the nav but in the right section.

Does anybody know what can be done to fix this? My guess is that the sticky navigation is causing an issue perhaps with the height? Making it seem shorter than it is when the nav is sticking?

Essentially it works until the sticky navigation comes into effect, what is the solution to get them to both to work together?

Answer

SweetTomato picture SweetTomato · Aug 20, 2013

A link that helped me work through some issues:

http://mtjhax.wordpress.com/2013/02/11/twitter-bootstraps-scrollspy-plugin-needs-better-docs/

Also important:

Set up Affix

Give the nav element a data-spy="affix", data-offset-top="", data-offset-bottom="" where offset from top or bottom tells the browser when to switch the positioning of the nav element. (Note: affix-top is usually position: static, affix is usually position: fixed, and affix-bottom is usually position: absolute.)

Get the positioning right

Make sure to set in your css a "position: _____;" and "top: __px" for each of these states. (Possibly, you only need to set a top for .affix, position & bottom for .affix-bottom, and nothing for .affix-top.)

Solve flickering issues

If you've had issues with flickering of the nav element when you've scrolled to the bototm (class switches rapidly between .affix and .affix-bottom), then you probably need to set position:relative on a parent element. I would recommend on a parent that takes up the full height that your nav will "travel", that way you can set bottom: 0 or bottom: [desired margin from bottom] for the .affix-bottom.

Initiate ScrollSpy with JS

You've initiated the affix portion of your page. Now lets initiate the spyscroll. Note that you can initiate spyscroll through data attributes or through js. Let's do js.

In the link above, just copying the code is dangerous because the "#" comment syntax broke my code (Switched # to // and all worked well).

Add this to the bottom of your body:

<script>
   // initiates scrollspy on body targeting the nav wrapper
   jQuery('body').scrollspy({ target: '#nav-wrapper' });
</script>

Note the use of body instead of the nav element like in the doc. Super important. Note that I am targeting the nav wrapper not the nav itself (if targeting the nav itself, the spying won't work, and instead the bottom li in the nav will always be highlighted)

Done

This was all a nightmare to discover, so hopefully it helps someone.

EDIT: My example. Note that the wrapper maintains its width so then the fixed navigation is not overlapping other content. (I had to give the nav itself a width so it didn't change sizes when jumping out of the nav wrapper).

<ul class="nav nav-list affix" data-spy="affix" data-offset-top="585" data-offset-bottom="425" id="prepare-navigation">
  <li class="nav-header">Where?</li>
  <li class="divider"></li>
  <li><a href="#at-the-museum-day-time">When?</a></li>
  <li class="divider"></li>
  <li><a href="#at-the-museum-overnight">Why?</a></li>
  <li class="divider"></li>
  <li><a href="#around-the-region">How?</a></li>
  <li class="divider"></li>
  <li><a href="#at-your-school-location">Etc?</a></li>
  <li class="divider"></li>
</ul>