Guategeek
Guategeek

Reputation: 51

Floating Images mess up Bootstrap Scrollspy

I have set up a page using bootstrap. (http://ethnoma.org/about.html) I have a sidebar navigation that is affixed (which is working great). I also am using bootstrap scrollspy on this navigation and all links in the navigation are within the same page (using ancors). Everything was working fine (even with a smooth-scroll plugin added). I simply had to call this script to force Scrollspy to refresh after all content is added to the page (which I placed in the <head>).

<script type="text/javascript">
// ScrollSpy
$(function () {
    $('[data-spy="scroll"]').each(function () {
        var $spy = $(this).scrollspy('refresh')
    });
});
</script>

My client then asked me to add images to the page. I did so using bootstrap markup and css classes like the following:

<a class="pull-right pad5" href="#">
    <img class="media-object img-polaroid" src="assets/img/about-001.jpg" alt="Partnership"/>
</a>

Which makes the parent "a" tag float to the right (in this case) and makes the img into a block element.

Problem is these floated images make the page longer than it was originally. Yet Scrollspy is still switching the active link at the same place. This causes scrollspy to activate links for content farther down the page than you currently are.

I am at a loss for how to force Scrollspy to take the floated images into account when calculating the location of the ID's the ancors link to. Do any of you have an idea how I could fix this. You can see the problem in effect at the following page http://ethnoma.org/about.html

Upvotes: 5

Views: 1384

Answers (2)

Heston Liebowitz
Heston Liebowitz

Reputation: 1685

I just came across this issue myself, so I thought I'd provide some explanation, and a possible solution, in case anyone else finds themselves in this bind.

First, scrollspy is working correctly. At the time that it computes the offsets of the various elements on the page, the images haven't loaded yet, so they have an effective height of 0. Later, when the images load, the browser determines their native dimensions, recalculates the page layout, and then repaints the page with the images. However, scrollspy is completely unaware that the page has been repainted, so it continues to use the stale offsets.

If you were to refresh scrollspy after all the images loaded, you'd find that the offsets would be correct. So, the question is how to do this.

One solution is to attach an onLoad event handler on every image, and then refresh scrollspy inside the handler. A simplified approach might look like this:

<script type="text/javascript">
    function refreshScrollspy() {
        $('[data-spy="scroll"]').each(function() {
            $(this).scrollspy('refresh');
        });
    }
    $(function() {
        refreshScrollspy();
    });
</script>

<img onload="refreshScrollspy()" src="assets/img/about-001.jpg" alt="Partnership"/>

Here's a working jsfiddle example. Note that that image's load handler has to be registered before the image actually loads. Otherwise, it won't get fired. That's why I'm using an inline event handler here. A more elegant solution is left to the reader.

Upvotes: 2

Nelson Wong
Nelson Wong

Reputation: 51

Came across this issue myself while trying to use the Scrollspy from Bootstrap, and it seems that the script doesn't take into account of the image's height while calculating, thus causing the Scrollspy to be in accurate.

I believe this is due to that the image doesn't have a height set to it. By inspecting the page, I have found that the floating images I have included in the page had the height set to auto, and when I've set it to a specific value after media queries in the CSS, my Scrollspy was working perfectly.

Upvotes: 1

Related Questions