Foundation-sites: [Sticky] Sticky Elements Do Not Stick After Adding Dynamic Content

Created on 17 Jan 2016  路  5Comments  路  Source: foundation/foundation-sites

Using Foundation 6.1.1.

How can we reproduce this bug?

STEP 1. Add a sticky top element to a new html page... here's an example:

    <div data-sticky-container>
      <div class="sticky" data-sticky data-options="stickTo:top; stickyOn:small;">
        <div class="top-bar">
            My Topbar Content
        </div>
      </div>
    </div>

STEP 2. Add a div containing 100 lines of content to the body of the page:

<div id="mycontent">
Line 001<br>
Line 002<br>
...
Line 100<br>
</div>

STEP 3. Preview the page. Scroll to the bottom. The top-bar is sticky. Life is good.

STEP 4: Remove the 100 lines from the div you added in step 2 (keep the empty div).

STEP 5: Add the following javascript which adds 100 lines programmatically:

    <script>
        $(document).foundation();
        for (i=1;i<101;i++) {
            $("#mycontent").append("Line " + i.toString() + "<br>");
        }
    </script>

STEP 6. Preview the page. Note the last visible line number (in my case it was Line 028). Scroll to the bottom. You will notice that when the last visible line (in my case, Line 028) reaches the top of the browser, the top-bar is no longer sticky.

What did you expect to happen?

I expected the top-bar to remain sticky.

What happened instead?

The top-bar scrolled away.

Test case

The above steps provide a reproducible scenario.. Here is a video demonstrating the issue: http://screencast.com/t/JEfPxED0wlld

javascript 馃悰bug

Most helpful comment

There's actually a way to do this baked into sticky, though when I was writing it, I initially 'privatized' the function. if you do this:

//add dynamic content...
$('.sticky').foundation('_calc', true);

it will recalculate the points on the page, and you can recalc as much as you like. The argument of true tells the plugin to reset the sticky points, if there's no arg or it's falsey, it'll just set or remove sticky like normal.

All 5 comments

THERE IS A WORKAROUND!!!!

  1. In my original page, I do NOT add "data-sticky" to my desired sticky element. All other sticky config is in place as normally required, like my data-sticky-container, etc.
  2. After dynamic content is loaded, I add the data-sticky attribute to my sticky div, and re-call foundation() on it:
$("#sticky-mobilemenu").attr("data-sticky", "true").foundation(); 

There's actually a way to do this baked into sticky, though when I was writing it, I initially 'privatized' the function. if you do this:

//add dynamic content...
$('.sticky').foundation('_calc', true);

it will recalculate the points on the page, and you can recalc as much as you like. The argument of true tells the plugin to reset the sticky points, if there's no arg or it's falsey, it'll just set or remove sticky like normal.

Thank you for the solution!

I get an error on my page when I execute the recommended statement, since one of my two sticky items is always hidden: _Uncaught TypeError: cb is not a function (foundation.sticky.js:330)_

To address the issue, I use:

$('.sticky:visible').foundation('_calc', true);

If anyone would have any idea why I'm told

We're sorry, '_calc' is not an available method for this element

http://stackoverflow.com/questions/36409146/foundation-6-sticky-calc-is-not-an-available-method-for-this-element

I also found a work-around for the problem. There is a property in the .data('zfPlugin') called .bottomPoint. This sets the lower point to where it may scroll. I'm using jQuery ($) as tool of preference.

// this should be placed (and edited) before content is added
var $container = $('#name-of-dynamic-container')
    newHeight,
    currentHeight = $container.height();

// ... adding content ... 

// this should be placed after content is added AND any animation is done
// use a timeout if necessary.
newHeight = $container.height();

// this adds the new space to 
$('#specific-sticky').data('zfPlugin').bottomPoint += (newHeight - currentHeight);

There is no need to re-initialize anything. Feel free to shoot me for this solution being hackish, but it worked for me.

_A note: Using height() may not take margins or padding into consideration or calculate padding correctly. .outerHeight() may perform a better task on that behalf, but height() sufficed for my 'problem'_

Was this page helpful?
0 / 5 - 0 ratings