Search code examples
angularjsios7mobile-safaricss-positioniscroll

"Fixed" header and footer with scrolling middle in Web-app on iOS 7.1.2


I have created a quite simple demo web-app, core-layout, using AngularJS with optional support for using iScroll 5. (Update: the version linked to on GitHub pages is now fixed, as shown in my answer below. If you want to see how this problem behaved, either look at the attached images or checkout version v1.2.1 and build the examples locally).

I am aware of the issues with elements with CSS position: fixed on iOS 7.x. For example, when you activate input elements, fixed positioned elements move around, and I've read about how Google's Gmail team had to turn off native scrolling and animate the scrolling area themselves. Therefore, I made the app layout use CSS position: absolute directives on the header and footer when iScroll is toggled on. However, if the iScroll is toggled off, the layout use position:fixed, which works very well with newer browsers on both mobile and desktop.

I have manually tested that the app renders and behaves as expected on several mobile devices, including both iOS and Android devices.

However, in Safari on an iPhone 5s with iOS 7.1.2, with iScroll on, the header is hidden behind Safari's address bar, and the footer is rendered too low on the screen, so it gets hidden behind Safari's footer menu, as shown in the following screen shot:

initial view, iScroll: on, position: absolute

Then, when I manage to get hold of the header menu, I can pull it downwards, so that the header menu becomes visible, but the footer menu is then still hidden:

pulled header menu down, iScroll: on, position: absolute

If I then manage to push the header menu upwards, the footer menu slides in to become visible at the bottom of the screen, above Safari's own footer menu:

pushed header menu up, iScroll: on, position: absolute

If I turn iScroll off, and thereby also change to position the header and footer menus with position: fixed. all renders OK, but the scrolling field has no momentum (and therefore feels a bit off), and I'll probably have to fight with fixed-position elements jumping around screen when input fields get activated (triggering iOS' on-screen keyboard):

on top, iScroll: off, position: fixedscrolled to bottom, iScroll: off, position: fixed

When I test the same web-app on an iPad running iOS 7.0.6, the same problem does not occur.

The source code is of course available on GitHub. Now, I wonder what I am doing wrong and how can this problem be fixed?


Solution

  • I went back to one of the relevant sources, the simple iScroll example (which works as expected, even in Safari on iOS 7.1.2), and studied the code, looking for significant code differences between that demo and mine. I discovered that the meta viewport tag had a different value. The solution was actually quite simple, and at least partly, meaningful.

    The solution was to change

    <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, target-densityDpi=device-dpi">
    

    to

    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, target-densityDpi=device-dpi">
    

    That is, to remove the height=device-height specification, which apparently is interpreted differently in Safari on iOS 7.1.2 and other, newer browsers.