Aus Linux-Magazin 08/2014

Webbrowser-Fensterbreiten-gesteuerte Anzeigelogik in Perl

© Tatiana Grozetskaya, 123RF

Damit sein Blog sowohl auf Desktop-Monitoren als auch auf modernen Mobiltelefonen mit hochauflösender Grafik gut aussieht, hat Perlmeister Schilli mit CSS und Media-Queries eine von der Browserbreite abhängige Umschaltautomatik gebaut.

Die Optik meines USA-Blogs Usarundbrief.com entlarvt, dass das Seitenlayout mehr als zehn Jahre auf dem Buckel hat. Auf dem Laufsteg sollen Modetrends ja alle 30 Jahre wiederkehren. Dass mein Webdesign in Kürze nochmals vorbeischaut und meine Seiten von allein wieder en vogue werden, halte ich dagegen für wenig wahrscheinlich.

Da bleibt mir wohl nichts anderes übrig, als selbst Hand anzulegen. Die Website hatte ich damals mit dem Perl-Template-Toolkit aufgezogen – unter strikter Trennung von Inhalt (jetzt auf Github [2]) und Layout. So sollte es nicht schwerfallen, die Seiten-Garderobe einer radikalen Designänderung zu unterwerfen.

Von bunten Kästen mit runden Ecken und anderem Firlefanz abgesehen, zeichnet sich gutes Webdesign heute vor allem dadurch aus, dass der Inhalt einer Website auf den kleinen Displays von Mobiltelefonen genauso lesbar ist wie auf einem Desktop-Monotor (Abbildung 1, [3]). Das lösen manche Site-Betreiber durch spezielle Mobilseiten, zu denen sie den Browser lotsen, sobald sie anhand des Useragent-Headers feststellen, dass der User im Moment auf ein Minidisplay in seiner Hand starrt. Die Mobilseiten verzichten dann beispielsweise auf Navigationselemente, die dicke Finger auf Smartphones gewöhnlich verfehlen.

Abbildung 1: Auf einem breiten Desktop stören Navigationselemente neben dem Inhalt nicht.

Abbildung 1: Auf einem breiten Desktop stören Navigationselemente neben dem Inhalt nicht.

Doppelt hält nicht besser

Nach der Lehre des Responsive Design stecken Webentwickler aber nicht eigenen Aufwand in besondere Mobilseiten, sondern gehen einen Ressourcen sparenden Weg. Mittels CSS und so genannter Media-Queries antwortet eine HTML-Seite mit jeweils passenden Leistungsmerkmalen auf die Displays: Auf kleinen Bildschirmen fallen manche Navigationselemente weg, Logos schrumpfen und meist seitlich nebeneinander platzierte Bereiche reihen sich untereinander an.

Online PLUS

In einem Screencast demonstriert Michael Schilli das Beispiel: https://www.linux-magazin.de/2014/08/plus.

Mit Zwicker und Leselupe

Vor allem stört bei meinem Blog ein Feature von Smartphone-Browsern: Trotz kleinen Displays schneiden sie aufgerufene Seiten nicht ab, sondern zoomen so weit heraus, dass die gesamte Seitenbreite erscheint. Bei für PC-Displays gebauten Seiten kann das kein Mensch lesen, und der mobile User hat beide Finger voll zu tun, mit Gesten auf eine lesbare Schriftgröße zu kommen und per Panning wie mit einer Lupe im Inhalt herumzufahren (Abbildung 2).

Eine Seite, die nun alle Displaygrößen gleichermaßen bedient, schaltet zuerst das Zoom-Feature ab. Mit dem Tag

<meta name="viewport" content="width=device-width,initial-scale=1.0">

im Headerteil des HTML-Dokuments bricht nun (gewollt) auf kleinen Displays das Chaos (Abbildung 3) aus: Der Browser schneidet gnadenlos den rechten Teil der Seite ab, Teile des Inhalts auf der linken ebenfalls. Statt auf den Inhalt blickt der User manchmal auf riesige Logos und Navigationselemente. (Der Desktop-User bleibt verschont, denn er sieht nach wie vor das Original-Layout.) Klar ist: Nach diesem ersten Schritt muss die Seite ihren Inhalt dynamisch neu strukturieren, sobald sie bemerkt, dass ein Handy-User darin herumstöbert.

Abbildung 2: Das iPhone zeigt die Seite auf große Distanz, sodass sie zwar in voller Breite erscheint, aber ohne Zoomen nicht lesbar ist.

Abbildung 2: Das iPhone zeigt die Seite auf große Distanz, sodass sie zwar in voller Breite erscheint, aber ohne Zoomen nicht lesbar ist.

Abbildung 3: Die HTML-»meta«-Anweisung an den Viewport unterdrückt die Zoomfunktion des iPhone. Die Folge ist abgeschnittener Text.

Abbildung 3: Die HTML-»meta«-Anweisung an den Viewport unterdrückt die Zoomfunktion des iPhone. Die Folge ist abgeschnittener Text.

Handy mit Monstermonitor

Die Vielfalt der Geräte erschwert die Lage: Ein iPad Mini mit Retina-Screen verfügt über eine Auflösung von 2048 mal 1536 Pixeln, mehr als die meisten Desktopmonitore. Selbst Smartphones wie das HTC One erreichen auf nur 12 Zentimetern Diagonale sagenhafte 1080 mal 1920 Pixel Auflösung. Eine Webseite, die für eine breite Palette von Endgeräten die optimale Darstellung wählt, muss also nicht nur die Auflösung des verwendeten Displays berücksichtigen, sondern auch die Pixeldichte, damit sie nicht zu viele Informationen in zu wenig Raum zwängt.

Switchen per Media-Queries

Wie zum Beispiel [4] erläutert, schalten moderne Webseiten die Darstellung über so genannte Media-Queries um. Der CSS-Teil einer Seite fragt ab, wie breit ein Viewport ist, also die aktuelle Größe des Browserfensters, und aktiviert, deaktiviert oder verschiebt entsprechend ausgezeichnete »<div>« -Elemente im HTML-Teil. Das passiert Client-seitig im Browser, der Server liefert stets die gleiche Seite aus und merkt nichts von der sich dynamisch anpassenden Darstellung.

Listing 1 zeigt als Beispiel den HTML-Teil einer Seite mit einem Navigationselement mit der ID »nav« und einem Textteil namens »main« . Der davor stehende Headerteil der Seite, den die »INCLUDE« -Anweisung des Perl-Template-Toolkits hereinzieht, befindet sich in Listing 2. Er birgt neben der eingangs erläuterten Viewport-Anweisung zum Ausschalten der Handy-Zoomfunktion einige statische CSS-Anweisungen sowie zwei mit dem Schlüssel »@media« eingeleitete Media-Queries, die die weiter oben stehenden statischen Anweisungen überschreiben, falls sie feststellen, dass das Endgerät bestimmte Voraussetzungen erfüllt.

Listing 1

test.html.tt

1 [% INCLUDE 'header.html.tt' %]
2 <body>
3     <div id="nav">
4       Navigation Bar
5     </div>
6     <div id="main">
7       Main Content
8     </div>
9 </body>

Listing 2

header.html.tt

01 <!DOCTYPE html>
02 <html>
03   <head>
04     <meta name="viewport"
05      content="width=device-width,initial-scale=1.0">
06   <style>
07
08   #nav {
09     float: top;
10     display: block;
11     border: 6px solid green;
12   }
13   #main {
14     float: bottom;
15     display: block;
16     border: 6px solid pink;
17   }
18
19 @media only screen and (max-width: 640px),
20     only screen and (max-width: 1080px) and
21       (-webkit-min-device-pixel-ratio: 2.0) {
22     [% INCLUDE hidenav.css.tt %]
23 }
24
25 @media only screen and (orientation: landscape) {
26     [% INCLUDE sidebyside.css.tt %]
27 }
28
29   </style>
30 </head>

Nur für neue Browser

So bestimmt die Media-Query (Zeile 19, Listing 2) mit dem einleitenden Kommando »only screen and …« , dass sie nur auf Bildschirmdarstellungen reagiert (also nicht in der Druckdarstellung) und mit »and« weitere, nachfolgende Bedingungen verknüpft. Das Schlüsselwort »only« weist ältere Browser ab, die die nachfolgende Query eh nicht verstünden.

Die Query »max-width: 640px« passt auf alle Browser, deren Fenster schmaler als 640 Pixel ist. Durch ein Komma getrennt folgt eine weitere, mit einem logischen Oder verknüpfte Bedingung, die wiederum eine »screen« -Bedingung voraussetzt und auf hochauflösenden Retina-Displays mehr Pixel in der Breite zulässt. Der Wert für »-webkit-min-device-pixel-ratio« ist für einen altgediegenen Monitor 1,0 und auf einem Retina-Display 2,0, wie sich mit Hilfe von [5] feststellen lässt (Abbildungen 4 und 5).

Auf Geräten mit kleinen Bildschirmen, egal ob diese mit Hochauflösung protzen oder nicht, holt die Media-Query aus Zeile 19 also die Datei »hidenav.css.tt« (Listing 3). Dies setzt den Wert für das Attribut »display« des »div« -Elements mit der ID »nav« auf »none« , unterbindet also die Darstellung des Navigationselements. Weiter belegt es die Variable »float« für das Inhaltselement »main« mit »top« , lässt das »div« -Element also am oberen Fensterrand schweben.

Abbildung 4: Auf einem Desktop-PC-Monitor ist die Pixeldichte 1,0.

Abbildung 4: Auf einem Desktop-PC-Monitor ist die Pixeldichte 1,0.

Abbildung 5: Zum Vergleich: Auf einem iPhone beträgt die Pixeldichte 2,0.

Abbildung 5: Zum Vergleich: Auf einem iPhone beträgt die Pixeldichte 2,0.

Listing 3

hidenav.css.tt

1   #nav {
2     display: none
3   }
4   #main {
5     float: top
6   }

640 Pixel sind die Grenze zwischen klein und groß

Ein auf die Webseite zugreifender Desktop-Browser zeigt, wie in Abbildung 6 zu sehen, sowohl den Navigationsbalken als auch den Block mit dem Text untereinander an. Schiebt der User das Browserfenster jedoch auf unter 640 Pixel Breite zusammen, schaltet der Browser wegen des adaptiven CSS-Layouts in den Mobilmodus, lässt das Navigationselement sausen und bringt nur noch den Textblock zur Ansicht (Abbildung 7).

Auf einem 640 Pixel breiten Display eines iPhone 5 erscheint wegen der Media-Query ebenfalls die Mobilversion ohne Navigation (Abbildung 8). Die zweite Media-Query in Listing 2 ab Zeile 25 fragt noch ein weiteres Darstellungsmerkmal der Anzeige ab. Mittels »(orientation: landscape)« prüft sie, ob die Anzeige im Querformat arbeitet. Ist das der Fall, kommt der Code in der Datei »sidebyside.css.tt« aus Listing 4 zum Einsatz, der Navigations- und Textelemente nebeneinander darstellt und dem Inhalt 70 Prozent einräumt und der Navigation nur 30 Prozent.

Abbildung 6: Ist das Fenster weiter als bis 640 Pixel aufgezogen, erscheint der Navigationsbalken.

Abbildung 6: Ist das Fenster weiter als bis 640 Pixel aufgezogen, erscheint der Navigationsbalken.

Abbildung 7: Verringert der User die Fensterbreite unter 640 Pixel, erscheint auch auf dem Desktop die Mobilversion der Seite.

Abbildung 7: Verringert der User die Fensterbreite unter 640 Pixel, erscheint auch auf dem Desktop die Mobilversion der Seite.

Listing 4

sidebyside.css.tt

1   #nav {
2     float: right;
3     width: 30%;
4     display: block;
5   }
6   #main {
7     float: left;
8     width: 60%;
9   }

Den Wert für die Variable »display« des Nav-Elements setzt Listing 5 auf »block« , um eine eventuell in der vorangegangenen Media-Query erfolgte Zuweisung des Wertes »none« zu überschreiben und den ursprünglich im statischen CSS-Anweisungsblock definierten Wert »block« wiederherzustellen. Eine Liste von Media-Queries arbeitet der Browser von oben nach unten ab und überschreibt bereits zugewiesene Werte, falls die vorgegebenen Bedingungen zutreffen.

Als Resultat erscheinen in Abbildung 9 beide Blöcke nebeneinander. Denn obwohl die erste Media-Query nur den Textblock ohne den Navigationsblock zulässt, überschreibt die Landscape-Query alle vorher getätigten Einstellungen und setzt beide Blöcke im Verhältnis 70 zu 30 nebeneinander.

Abbildung 8: Auf dem iPhone 5 erscheint wegen der Seitenbreite von 640 Pixeln die Mobilversion.

Abbildung 8: Auf dem iPhone 5 erscheint wegen der Seitenbreite von 640 Pixeln die Mobilversion.

Abbildung 9: Im Querformat erscheinen Inhalt und Navigationsleiste nebeneinander.

Abbildung 9: Im Querformat erscheinen Inhalt und Navigationsleiste nebeneinander.

Listing 5

mojo

01 #!/usr/local/bin/perl -w
02 use strict;
03 use Mojolicious::Lite;
04
05 @ARGV = qw( daemon --listen http://*:4080 );
06
07 plugin 'tt_renderer';
08
09 get '/' => sub {
10   my $self = shift;
11   $self->render('index');
12 };
13
14 app->start;
15
16 __DATA__
17
18 @@ index.html.tt
19 [% INCLUDE 'header.html.tt' %]
20 [% INCLUDE 'test.html.tt' %]

Baukastensystem

Das CPAN-Modul des Perl-Template-Toolkits baut die Seite aus den Template-Einzelteilen mit dem Kommando

tpage --include_path templatestemplates/test.html.tt >test.html

komplett zusammen und verbindet so die entwicklerfreundliche modulare Aufteilung mit voller Performance auf der Client- und Server-Seite.

Alternativ ließe sich der Browser anweisen bestimmte externe CSS-Seiten nur dann zu laden, wenn eine angegebene Media-Query einen wahren Wert zurückliefert. Doch kostet jeder Ladevorgang wertvolle Zeit – die vorkompilierte Webseite ist zur Laufzeit effizienter.

Wer schnell mit einem lokal laufenden Webserver testen möchte, kann dies mit einem kurzen Skript mit dem CPAN-Modul Mojolicious::Lite tun, wie in Listing 5 gezeigt. Es startet auf dem Localhost einen voll funktionsfähigen Server auf Port 4080. Ein darauf zugreifender Browser wird die Seite unterschiedlich anzeigen, je nachdem, ob das Browserfenster breit aufgezogen, mehr oder minder schmal zusammengeschoben oder ins Querformat gestellt ist. Um mit dem Template-Toolkit zu kommunizieren, benötigt das Skript das CPAN-Modul Mojolicious::Plugin::TtRenderer.

Wer tiefer in die Materie eindringen möchte, dem sei das Buch “Responsive Web Design with HTML 5 and CSS 3” empfohlen [6]. Es stellt eine Vielzahl praxisorientierter Anwendungsbeispiele vor und erläutert Techniken zum dynamischen Seitenlayout und zum Anpassen der Bildergrößen für verschiedene Mobil- und Desktopgeräte.

Infos

  1. Listings zu diesem Artikel: ftp://www.linux-magazin.de/pub/listings/magazin/2014/08/Perl
  2. Github-Repository mit dem Inhalt von Usarundbrief.com: https://github.com/mschilli/usarundbrief
  3. Apple Thunderbolt Display: https://www.apple.com/de/displays/
  4. Ethan Marcotte, “Responsive Web Design”, 2010: http://alistapart.com/article/responsive-web-design/
  5. Device pixel density tests: http://bjango.com/articles/min-device-pixel-ratio/
  6. Ben Frain, “Responsive Web Design with HTML 5 and CSS 3”: Packt Publishing, 2012

Der Autor

Michael Schilli arbeitet als Software-Engineer bei Yahoo in Sunnyvale, Kalifornien. In seiner seit 1997 erscheinenden Kolumne forscht er jeden Monat nach praktischen Anwendungen der Skriptsprache Perl. Unter mailto:mschilli@perlmeister.com beantwortet er gerne Fragen.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 4 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben