68

I've been developing a site and taking advantage from the rather good jQuery Sticky Kit plugin. It operates by switching the position property to fixed and back when appropriate. Runs very smoothly in desktop and acceptably so in mobile.

Or at least it used to. iOS 9 comes with a new behavior: if the position of an element changes from static/relative/absolute to fixed while the scroll animation is ongoing the element becomes invisible until after the scroll has come to a stop. Oddly enough the opposite change (from fixed to whatever else) is performed without issues.

A working example can be found on the plugin's homepage. The black navigation bar ("Examples Reference") is supposed to be sticky. Originally it's staticly positioned in mid-page. As you scroll down it becomes fixed and (in iOS 9) disappears until scroll stops. Behavior in desktop browsers and iOS 8 is correct.

I was kind of hoping for the typical CSS workarounds: forcing a 3D transform, disabling backface visibility and the like, obscure proprietary properties, ... But nothing seems to work.

Are we about to forget "stickable" elements altogether now that it was working?

Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58
instanceofnull
  • 1,071
  • 1
  • 7
  • 15
  • 2
    If you're developing for iOS you should use the better solution, `position: sticky` in CSS, albeit behind a prefix. You can keep your jQuery plugin for everything else and use the native CSS solution for iOS where it supports it (7+, if I recall correct). – TylerH Sep 30 '15 at 20:39
  • 1
    Well, I'm developing for everything, but this allows for a mixed approach. Thanks! – instanceofnull Sep 30 '15 at 20:46
  • 1
    A few hours into trial and error, I can conclude that support for sticky headers in iOS is pretty good, but everything goes haywire when you get to sticky columns. A bit too green still. – instanceofnull Oct 01 '15 at 11:06

5 Answers5

80

I had this same issue and was able to hack around it using the old "force a 3D transform" trick. Just set the element you are going to switch the position of to have a transform property of translate3d(0px,0px,0px). Make sure this is done before the position property is changed.

theblang
  • 10,215
  • 9
  • 69
  • 120
Nathan G
  • 987
  • 1
  • 7
  • 12
  • 15
    `translate3d()` caused some layout issues for me, but `translateZ(0)` worked a charm – nothingtosee Feb 23 '16 at 02:25
  • 3
    I had translate3d() on the same CSS class, the trick is that it should be there BEFORE changing the position or adding the new class. Thanks for that! – André Gil Jun 09 '16 at 09:57
  • 2
    this doesn't seem to work for me on iOS 10... well it works but I can break it by dragging such as the fixed element 'sticks' and then changing the direction of my drag in the other direction :-( – Simon_Weaver Oct 12 '16 at 20:29
  • Sadly this doesn't seem to work for me, on Safari 9.0. Nothing does. hide/show, adding an element, adding a CSS animation, accessing offsetHeight. I've tried every trick I can find, and still that header bar won't repaint in the fixed position until I remove my scrolling finger from the screen :( – Codemonkey Dec 16 '16 at 12:24
  • I literally spent days trying to figure out how to fix styling changes in my sticky header not taking affect until the scrolling completely stopped, making the whole thing look clunky and odd. Adding `transform: translateZ(0);` to the default element style fixed this and now the style transitions happen smoothly during scrolling. Wonderful! Thanks everybody! (Tested in Chrome and Safari on iPad Mini with iOS 10.0.2) – Katrin Jan 10 '17 at 12:09
19

The only solution that I found to work correctly was to disable z-index translations on direct children of the fixed item, e.g.:

.is-sticky > * {
    -webkit-transform: translateZ(0);
}
mik01aj
  • 11,928
  • 15
  • 76
  • 119
Seth Warburton
  • 2,234
  • 1
  • 16
  • 17
4

I fixed this problem with an extra fixed element. After some testing I found out that it's the first element that becomes fixed has this problem. The 2nd, 3rd, etc works fine on iOS devices.

So, put right after your body openingtag a div.fixed-fix:

.fixed-fix {
    position:fixed;
    top:-1px; 
    height:1px; 
    width:100%; 
    background:white;
}

now it works! The fixed-fix div MUST have a backgroundcolor, because otherwise it wont work...

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
  • 3
    this doesn't seem to work for me on iOS10. Maybe they 'fixed' it ? I was really hoping it would because I am finding the `translate` option very glitchy – Simon_Weaver Oct 12 '16 at 20:31
3

jQuery Sticky Kit and other similar plugins, even being well coded, are presenting this kind of behavior on iOS 9, and it is not the first time that something like this happens. The main point here is that Firefox Safari and Safari Mobile support the experimental position: sticky;, so did Google (Chromium) but, due to integration problems, has had to temporarily disable it, you can read more about it here. Having said that, my guess is that, very soon, position: sticky; will be part of the CSS specification and supported by all major browsers, thus I think the best approach to solve this issue is to use a polyfill instead of a plugin. Of course, a polyfill will not cover all the features and functionalities that these plugins offer. Nevertheless, in many situations, using a polyfill will do the work, as a robust and effective solution supported by all major browsers. In my opinion it is the way to go, for now. I personally use stickyfill although I am sure other polyfills in the wild will do the trick. All I can say is that, since I started using a polyfill instead of plugins, I have not had any browser compatibility issues.

0

Add this to your fixed element
Using a Mixing: @include transform(translate3d(0px,0px,0px))
Using CSS: translate3d(0px,0px,0px)

Yaron
  • 47
  • 3
  • 4
    *Using "SCSS"* is just wrong. What you recommend to use is a mixin, probably from compass... – yckart Mar 22 '16 at 14:50
  • 1
    Using SCSS is not wrong it's simply a way of saving yourself the trouble of having to type in every single browser prefix. – Zanderi May 26 '16 at 18:33
  • 2
    .... urm.... except this is [probably] just an iOS '.issue' and therefore you don't need to worry about any prefixes – Simon_Weaver Oct 12 '16 at 03:19