16

In mobile safari, in the course of handling touchmove for an element, I change the className of that element. Unfortunately, the visual change does not occur while the user is scrolling, or until the very end of an inertial scroll.

What can I do to get the className to visually take immediately?

More: Apparently this isn't limited to className changes, but seemingly any change to the DOM, such as innerHTML and style.

Hilton Campbell
  • 6,065
  • 3
  • 47
  • 79

3 Answers3

15

I actually built that site, and yes the way to get around this limitation is to not scroll the site using the built in browser functionality but fake it. The JS listens to scroll wheel and keyboard events and tweens the css top property of the main container to its own 'scrollTop'. The scrollbar on the right is of course a custom JS one. In this case its synced to the same internal 'scrollTop' value.

The whole site is just one big tween really, with the main timeline being its scrollTop position, and all the sub animations being triggered at certain times. The JS isn't minified so take a look in the ScrollAnimator.js file, its all there.

rje
  • 390
  • 2
  • 8
13

This is by design unfortunately. iOS safari will queue up all DOM manipulation until the end of a scroll or gesture. Effectively the DOM is frozen during a scroll.

I thought I could find a reference to this on an apple developer page, but I can only find this link to jQueryMobile: http://jquerymobile.com/test/docs/api/events.html.

Note that iOS devices freeze DOM manipulation during scroll, queuing them to apply when the scroll finishes. We're currently investigating ways to allow DOM manipulations to apply before a scroll starts

Hope this helps!

Andy
  • 2,977
  • 2
  • 39
  • 71
  • Upon reflection, I guess it's so heavy DOM manipulation doesn't slow down the lovely inertia of the scroll. – Andy May 11 '12 at 13:15
  • Sadness. The more I tried, the more clear it became that this is the case. – Hilton Campbell May 11 '12 at 13:42
  • Somehow, this site overcomes that limitation. Anyone understand what they did? https://victoriabeckham.landrover.com/INT – Jo Sprague May 24 '12 at 15:55
  • 1
    Very nice effect! I might be wrong, but it looks like they are overriding the scroll (in their touchMoveHandler method in ScrollAnimator.js they are using event.preventDefault) and just animating the visible area to look like a scroll is occurring. May be wrong, only look at it for a few mins, but it looks like thats the case! :) – Andy May 25 '12 at 07:36
  • A bit after the fact but [facebook home](http://facebook.com/home) does this fine on mobile (ipad) – nbsp Aug 13 '13 at 02:03
  • Facebook Home is an app, not a webapp and so isn't restricted by iOS Safari issues – Dancrumb May 14 '14 at 19:06
  • This is fixed in iOS8. Setting only a translateY on iOS7 works, albeit a bit choppy. – Paul Hachmang Sep 15 '14 at 20:04
  • @PaulHachmang its definately not fixed yet on iOS safari. I am using iOS9, still same issue – ey dee ey em Apr 12 '16 at 14:17
4

Simply change position to -webkit-sticky. Do not set top so it will look just like a normal element, but performs like a fixed element. And you can update its style except position immediately.

jimm-cl
  • 5,124
  • 2
  • 25
  • 27
bumfo
  • 254
  • 3
  • 6
  • this works beautifully in iOS and newer versions of desktop safari. What I did for the header was specifically for iOS I use this property, everything else uses the fixed, this is because of compatibility. More about this property here: http://updates.html5rocks.com/2012/08/Stick-your-landings-position-sticky-lands-in-WebKit – loriensleafs Aug 28 '14 at 19:06
  • This! Incredible! I've been pulling my hair out for days trying to find solutions to animate something during touchmove and position: sticky; is exactly what I needed. I would have never come up with this on my own. Thank you so much! – beefchimi Sep 14 '14 at 00:01