Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 406
Guategeek Avatar asked Oct 22 '22 13:10

Guategeek


1 Answers

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.

like image 169
Heston Liebowitz Avatar answered Oct 24 '22 04:10

Heston Liebowitz