Twitter | RSS | Archiv

Thomas goes .NET

Das persönliche Blog von Thomas Bandt.

HTML & CSS - Scrolling in Mobile Safari und Android Browser

Als Steve Jobs seinerzeit das iPhone ankündigte, war von einem SDK und nativen Apps noch keine Rede. Die Zukunft sollte mobilen Applikationen gehören, HTML5 bekam erstmals richtigen Buzz-Charakter.

Zwar ist es Apple seinerzeit gelungen mit der mobilen Variante von Safari erstmals einen Browser auf ein Smartphone zu bringen, der seinen Namen auch verdient. Doch als Anwendungsplattform ist er dennoch vieles schuldig geblieben, beispielsweise die Möglichkeit, Dateien hochzuladen.

Das geht zwar unter Android problemlos, doch basiert der Android-Browser ebenfalls auf Webkit und bietet demzufolge neben den gleichen Rendering-Ergebnissen und Features auch die gleichen Unzulänglichkeiten - und mehr.

Worauf will ich hinaus? Ganz einfach: Eine Applikation auf einem mobilen Gerät sollte aus Anwendersicht mit einem klaren Layout aufwarten. Oben eine feststehende Titelleiste, dazwischen der Inhalt, unten Navigationsbuttons, ebenfalls feststehend. Dies lässt sich in modernen Desktop-Browsern problemlos erreichen, in dem man die drei Elemente, also Header, Content und Footer, fix positioniert, ihnen eine feste Größe zuweist (dem Content per JavaScript, damit er sich mitstreckt) und dem Content-Bereich die CSS-Anweisung overflow:scroll/auto mitgibt. Damit werden Scrollbars im Inneren angezeigt, sobald der Inhalt höher oder breiter als der ihn beinhaltende Container ist.

Das ist mit den mobilen Webkit-Browsern nicht möglich. Es gibt weder eine Unterstützung für position:fixed noch für overflow:scroll. Scrollbare Inhalte innerhalb einer Website sind nicht vorgesehen - es kann immer nur die gesamte Website gescrollt werden. Für Websites ist das in Ordnung, für Webanwendungen ein Problem.

Die überlangen Inhalte werden dann einfach abgeschnitten. Unter iOS kann man noch mit zwei Fingern scrollen, was natürlich kein Anwender versteht - zumal auch dann keine Scrollbar angezeigt wird. Unter Android ist nicht einmal das möglich.

Nun kann man die Sache natürlich auf verschiedene Arten betrachten.

Warum überhaupt scrollen?
Sicher, eine berechtigte Frage. In den allermeisten Fällen, sollte sich das sogar vermeiden lassen. Etwa durch den Einsatz von Paging für Listen, etc. Das ist aber nicht nur wenig anwenderfreundlich, sondern auch ziemlich gewagt. Denn es gibt dermaßen viele verschiedene Geräte auf dem Markt mit sehr vielen unterschiedlichen Auflösungen (sogar quadratische Displays!), dass quasi nie sichergestellt werden kann, dass der Inhalt von der Höhe auch wirklich auf den Bildschirm passt.

Scrollen - na und?
Auch ein Ansatz, und übrigens der, den ich schlussendlich gewählt habe. Für Smartphones ist das Scrollen kein wirkliches Problem, da man z.B. auf dem iPhone mit einem Tipser oben auch ganz schnell wieder an den Seitenanfang gelangt. Zum Anderen kann man z.B. durch Verwendung von min-height ganz geschickt erreichen, dass die Anwendung sich für Fälle, in denen der Inhalt nicht überlang ist, zumindest über die volle Fensterhöhe streckt, und so auch nach Anwendung ausschaut. Darüber hinaus hat der Nutzer bei langen Inhalten immer den vollen Bildschirm zur Verfügung, es wird kein Platz durch die Title- oder Footerbar verschwendet.

Nur auf Tablets ist es ein echtes Problem, da hier ein gewohntes Layout, wie z.B. von der Einstellungs-App auf dem iPad gewohnt, schlicht nicht realisierbar ist. Denn warum auf der linken Seite für eine Navigationsleiste Platz reservieren, die dann aus dem Sichtfeld herausscrollt?

Vorhandene Lösungsansätze
Es gibt verschiedene Open-Source-Libraries, die es sich zum Ziel gesetzt haben, das Problem zu beseitigen. Hier erst einmal die Liste der von mir evaluierten:

  1. iScroll 4
  2. YUI 3 ScrollView
  3. Scrollability
  4. jScrollPane

Alle vier eignen sich gut, um einfache HTML-Listen scrollbar zu machen. Die ersten drei sind hingegen sind leider völlig unbrauchbar, wenn der zu scrollende Inhalt komplexer wird - wenn es sich etwa um ein großes Formular mit vielen Elementen handelt. Durch die verwendeten CSS-Transformationen entstehen nicht nur seltsame Seiteneffekte, die Anwendung wird auch langsam und führt z.T. auch zu reproduzierbaren Browser-Abstürzen.

jScrollPane hingegen ist eine Komponente, die Touch-Geräte gar nicht primär im Blickfeld hat, aber dennoch ganz wunderbar funktionieren kann. Kann, weil auch sie sich schwer tut, sobald CSS3-Effekte und komplexe DOM-Strukturen zum Einsatz kommen. Wenn man darauf aber verzichten kann, ist es eine Option.

Ich habe mich schlussendlich dagegen entschieden, da das Scrolling von der Erfahrung für den Benutzer nicht gut genug ist. Man ist es gewohnt schnell mit dem Finger durchtappen zu können, das geht hier natur gemäß alles nicht. Also lieber eine Anwendung mit verschwindender Header- und Footerleiste, die man schnell durchscrollen kann, als eine nach nativer App ausschauende Anwendung, die langsam und träge ist.

CSS und jQuery - da muss doch noch was gehen ...
Das dachte ich mir, und baute ein paar eigene Prototypen. Der Grundansatz ist folgender: ich zeige absolut von oben positioniert den Header und den Footer an, der immer über dem normalen Inhalt liegt, welcher nativ gescrollt werden kann, und nach oben wie nach unten einen Abstand in Höhe der beiden Leisten besitzt. Sobald der Benutzer an eine andere Stelle im Dokument scrollt, werden auch die beiden Leisten umpositioniert.

Es funktioniert. Aber leider nicht wirklich ansprechend. Es gibt mehrere Touch-Events, die zur Erkennung von Benutzereingaben auf Touch-Geräten verwendet werden können. Leider gibt es für die Erkennung von Scrolling nur zwei: touchstart und touchend.

Wenn man scrollt, scrollt man auch die absolut positionierten Leisten mit weg. Um diesen Effekt zu vermeiden (die Footerbar schiebt sich z.B. nach oben), sollte man die Leisten in touchstart ausblenden.

Idealerweise würde man sie in touchmove einfach umpositionieren - was leider nicht geht. Bleibt also touchend, wo man sie wieder einblendet. Das Problem: touchend wird wirklich erst ganz zum Schluss aufgerufen. Wenn also die Seite langsam ausrollt, wie man das vielleicht kennt, wenn man "größere Strecken" wegscrollt, dann hat man eine deutlich sichtbare Verzögerung, die teilweise im Sekundenbereich liegt, bevor die Leisten wieder angezeigt werden. Für mich keine Option.

Die Zukunft ab iOS 5 - alles wird gut. Irgendwann.
Apple wird mit iOS5 die Unterstützung für position:fixed als auch overflow:scroll einführen, was all die Probleme lösen wird, die ich oben beschrieben habe. Leider ist iOS 5 heute noch nicht verfügbar. Und bis sich die Änderungen auch unter Android verbreitet haben, wird noch einmal viel Zeit vergehen - man darf nicht vergessen, dass Android die eigentliche Zielplattform ist, mit wesentlich mehr Geräten weltweit, als bei Apple.

Kommentare

  1. Ralf schrieb am Sonntag, 22. Januar 2012 16:51:00 Uhr:

    Das Problem hatte ich die ganze Zeit auch beim Android (auf dem PC in VirtualBox) und jetzt funktioniert es mit CSS position:fixed auf einmal. Ich weiß nicht ob Android da irgendwie ein automatisches Update gemacht hat, jedenfalls funktioniert es zu meinem Erstaunen.
  2. Thomas schrieb am Sonntag, 22. Januar 2012 20:16:00 Uhr:

    Meines Wissens nach nur mit Android 4.0 - hier ist die neue Webkit-Engine drin, die auch Apple mit iOS 5 ausgeliefert hat (da geht es nun auch). Hilft leider erst in frühestens 2 Jahren weiter, wenn Android < 4.0 ausgestorben ist. Wenn es überhaupt so schnell geht, ich denke 2.x und 3.x dürfte sich eine ganze Weile halten.
  3. Andreas schrieb am Dienstag, 24. April 2012 12:29:00 Uhr:

    Also bei Android 3.2 geht das mit position: fixed;. Ich arbeite gerade auch an einer Webanwendung speziell für Android-Tablets. Dabei bin ich auch auf ein paar Probleme gestoßen - das mit den Browserabstürzen und dass (obwohl event.preventDefault(); auf touchmove und -start gesetzt, da ich alles selbst programmiert habe) in seltenen Fällen nativ gescrollt wird, was es aber nicht soll. Werde mal sehen, ob ich dennoch irgendwie natives Scrollen verwenden kann..