'Twitter Bootstrap scrollspy always selecting last element
I have an issue with scrollspy, recreated in this fiddle: http://jsfiddle.net/jNXvG/3/
As seen in the demo, the ScrollSpy plugin always keeps the last menu item selected no matter the scrolling position. I've read other questions and answers and tried different combinations of offset, etc., but none of them have helped. I can't figure out what's wrong.
I don't want to edit my template to include ugly html 'data' tags, so I am calling scrollspy() via JavaScript to activate the plugin.
The next step would be to remove the fixed content height and use 'affix' on the sidebar.
Solution 1:[1]
You need to attach the ScrollSpy to the element that is going to trigger scroll events, rather than the menu that is going to reflect the scroll position:
$('#content').scrollspy();?
JSFiddle
Solution 2:[2]
I had the exact same problem and for me, adding height: 100% to the body element was the fix.
(stricly nothing else seemed to make it work)
Solution 3:[3]
FYI: To get my desired effect (same one as on the Twitter Bootstrap docs page) I needed to set 'body' as my target element...I could not get scrollspy'ing to work by using the immediate parent of the elements I wanted to spy as the target.
(It just auto-selected the my last element always)
Solution 4:[4]
In my case, Firefox was always selecting the last element and it was NOT the
height:100%;
on the body that was causing the problem (as I didn't have anything like that).
It was a
position:absolute;
on a container div.
Hope it helps someone out there...
Solution 5:[5]
I fixed it using body height 100% but it didnt work on Firefox. After wasting so much time found the answer on github page. Applying height 100% to HTML tag fixes the issue both for Chrome and Firefox.
Solution 6:[6]
When calling the scrollspy method you typically specify the body tag and the nav element.
<script>
$(function() {
$('body').scrollspy({ target: '#faq_sidebar' });
});
</script>
The JavaScript above is equivalent to:
<body data-spy="scroll" data-target="#faq_sidebar">
The only situation where you do not specify the body tag is if you want to track an element with a nested scrollbar like in the JSFiddle above.
Solution 7:[7]
If anyone else's issue wasn't solved by the suggestions above try adding <!DOCTYPE html> to the first line of your page. This was a simple step which solved the problem for me.
Solution 8:[8]
I had this same problem; removing the height: 100% from the <body> element fixed this for me.
Solution 9:[9]
I had a similar issue where scroll spy would not work on anything but a body tag so I actually went into the bootstrap js found the Scroll spy (SCROLLSPY CLASS DEFINITION) section and changed this line:
, $element = $(element).is('body') ? $(window) : $(element)
to this:
, $element = $(element).is('body') ? $(window) : $(window) //$(element)
(note that the element after the // is a comment so I don't forget I changed it)
And that fixed it for me.
Solution 10:[10]
ScrollSpy is pretty unforgiving and the documentation is sparse to say the least...there are different and conflicting fixes for this based on your implementation...
Nested content was my problem. This fixed it for me:
(1) make sure all hrefs in your nav match a corresponding ID in your spied upon target container.
(2) If the items in your spied upon content container are nested then it won't work...
This:
<ul class="nav" id="sidebar">
<li>
<a href="#navItem1" />
</li>
<li>
<a href="#navItem2" />
</li>
</ul>
<div id="spiedContent"> <!-- nested content -->
<div id="navItem1">
<div id="navItem2"></div>
</div>
</div>
To This:
<ul class="nav" id="sidebar">
<li>
<a href="#navItem1" />
</li>
<li>
<a href="#navItem2" />
</li>
</ul>
<div id="spiedContent"> <!-- flat content -->
<div id="navItem1"></div>
<div id="navItem2"></div>
</div>
All good!
My guess if you looked at the scrollspy code its not looking past the first child of the spied container for the ids.
Solution 11:[11]
Make sure you're not mixing implementations. You don't need $('#content).scrollspy() if you have data-spy="scroll" data-target=".bs-docs-sidebar" on your body tag.
Solution 12:[12]
I think that this might be a bug in ScrollSpy.
I also had the same problem and when I stepped through the code I could see that the offset for all the targets were the same (-95px). I checked where these were being set and it was using the position() function. This returns the position of the element relative to the offset of the parent.
I changed this to use the offset() function instead. This function returns the position of the element relative to the offset of the page. Once I did this then it worked perfectly. Not sure why this isn't the default behaviour.
The reason that the position() function wasn't working in my case was because I had to have an empty div which was actually absolutely positioned 95px above the top of its container. I needed this as my target so that the headings weren't hidden behind my header that was fixed to the top of the page.
Solution 13:[13]
When I was trying to figure out this issue, I used some of what Mehdi Benadda said and added position: relative; to the body. I added this to the stylesheet:
body {
position: relative;
height: 100%;
}
Hopefully this helps someone in the future.
Solution 14:[14]
You don't have to call method scrollspy(). Also you don't need set height: 100% anywhere.
All you need is:
- position: relative; for body
- add data-bs-spy="scroll" to your content or body
- add data-bs-target with navbar id
https://i.imgur.com/M5jib0t.png
It helps me.
Solution 15:[15]
It seems that scroll spy work only when used container has a scrollbar (Tested with bootstrap 5).
You can put data-bs-spy="scroll" and data-bs-target="#target-nav" attributes in the nearest parent having a scrollbar.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
