foundation-sites: Sticky component doesn't honor data-sticky-on attribute

How to reproduce this bug:

  1. Create a layout with sticky elements in accordance with the sticky component examples in the docs
  2. Set data-sticky-on="large" attribute on sticky elements

What should happen:

elements should only be sticky on large and all dom manipulations associated with the sticky component should not be applied on screen sizes smaller than the one specified in the data-sticky-on attribute.

What happened instead:

It seems like it’s trying to work but there are lots of side effects and it’s highly prone to jank. dom manipulations continue to occur on screens smaller than the one specified which can result in overlapping elements, disappearing elements, and other jankiness.

Test case:

Here’s a codepen that demonstrates the problem. This layout includes left nav, a main content area, and a right nav and utilizes source ordering and sticky sidebars. On mobile: Main content is full width, Left nav and Right nav are positioned below main content On medium: source ordering kicks in and moves the sticky left nav to the left of main content, right nav stays at the bottom On large: left nav is sticky, main content scrolls, right nav is sticky

For reference, here’s the same codepen without the sticky classes to demonstrate that the layot itself (i.e. the source ordering) is behaving as expected.

I hope the issue here is that I’m just not using the data-sticky-on properly 😃

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 9
  • Comments: 40 (8 by maintainers)

Most upvoted comments

I’m using Foundation 6.3.1 and have been fighting the issue described by @scottsawyer and @Ateker. Specifically, the one where the sticky element loads partway (or all the way) down the page on refresh or when navigating to another page and going back.

It’s inconsistent, which makes me think it has to do with the loading order. Foundation as a whole is typically initialized before $(document).ready(), but some plugins—like Sticky—clearly need to know the position of everything before they initialize, otherwise stuff like this is going to happen. I suspect the plugin is not waiting, which is causing this mess.

I started out just destroying the sticky things on page load when the screen is small (@gandalfar’s tip), but then they need to be reinitialized if the screen size increases (think rotating a device to portrait and back). Programmatically initializing sticky things has its own problem (#10505), which can be solved by manually triggering load.zf.sticky but then the console gets littered with errors and that’s yucky.

So, a workaround:

I noticed a couple of sticky.zf.unstuckfrom:top events fire on refresh, and whenever it bugs out there’s also a single sticky.zf.unstuckfrom:bottom (Note that none of this should be happening, since this is a small screen and stickyOn defaults to medium, but I digress). So, just listen for that buggy event to fire and remove the offending classes and styles from the sticky thing, which should put it back to its starting position.

// Prevent small screen page refresh sticky bug
$(window).on('sticky.zf.unstuckfrom:bottom', function(e) {
  if (!Foundation.MediaQuery.atLeast('medium')) {
    $(e.target).removeClass('is-anchored is-at-bottom').attr('style', '');
  }
});

If you have some custom inline styles (like width:100%) you may want to remove just the top style instead of wiping them all out.

I am also having this issue, when I set data-sticky-on=“medium”, when on a mobile sized screen, the plugin runs, but sets a top value of 10015.6px ( about the height of my screen ). This pushed the <div> to the bottom of my page, and I get classes add: “sticky is-anchored is-at-bottom”

If I set data-sticky-on=“small”, it is sticky and works as expected on mobile, but I really don’t want a sticky on mobile.

Full option set: <div class="header--bottom--wrapper " data-sticky data-stick-to="top" data-sticky-on="medium" data-margin-top="0" style="width:100%;"></div>

NOTE: this only happens when the page loads at some place other than the top. For instance, if you scroll down part way / all the way, and refresh, or scroll down -> click a link to a new page then go back. If you are at the top of the page, the <div> stays in the correct position, but clicking the back button is such a common behavior, I can’t let this go into production. Tested on Android 6.x and Chrome dev tools.

Would like to get this fixed for 6.4 (roughly 1 month out). @colin-marshall can you take a look, or shall I?

Can anyone else confirm that they still see this issue occurring using v6.6.1? I seem to be encountering the same issue using the latest Foundation release so just wanted to check if others still see this occurring. I’ve worked around it for now using Yorb’s code from his comment above: https://github.com/foundation/foundation-sites/issues/9892#issuecomment-322878472

I’m on 6.4.3 and I want to have sticky elements only for medium+ screens. Here is how I achieved it:

if (Foundation.MediaQuery.current == 'small') {
  $('.sticky').removeAttr('data-sticky');
}
$(document).foundation();

I’m using 6.4.4-rc1 and it is still an issue. I needed the element to be sticky on anything large or above.

Solution that worked for me:

A slight variation from the solution of @yorb $(window).on('sticky.zf.unstuckfrom:bottom', function(e) { if (Foundation.MediaQuery.atLeast('medium')) { $(e.target).removeClass('is-anchored is-at-bottom').attr('style', ''); } });

@sveetch It looks like destroy (and _destroy) incorrectly removes all JS plugins. There’s probably another ticket for this somewhere.

As a workaround, put this into app.js:

if (!Foundation.MediaQuery.atLeast('large')) {
  $('.sticky').foundation('_destroy');
}