Responsive Webseiten gestalten
Flexibel entworfene Webseiten können helfen, sowohl Nutzern von Mobil- als auch von DesktopgerĂ€ten ein gutes Anwendererlebnis zu vermitteln. Die Umsetzung erfordert allerdings einige Ăberlegungen.
Flexibel entworfene Webseiten können helfen, sowohl Nutzern von Mobil- als auch von DesktopgerĂ€ten ein gutes Anwendererlebnis zu vermitteln. Die Umsetzung erfordert allerdings einige Ăberlegungen.
Themen wie Mobile First, Performance sowie Vor- und Nachteile von Responsive Webdesign wurden im VorgĂ€ngerartikel [1] zum Thema ausfĂŒhrlich erklĂ€rt. Jetzt geht es darum, den praktischen Teil unter die Lupe zu nehmen: Wie weit lĂ€sst sich ein Layout mit MediaQueries umsetzen? Was passiert mit groĂen Bildern auf kleinen GerĂ€ten? Wie kann man Formulare benutzerfreundlich gestalten? DarĂŒber hinaus soll betrachtet werden, welche Techniken es momentan gibt, aber auch welche in Arbeit sind und in naher Zukunft die breite Masse erreichen.
MediaQueries sind ein mĂ€chtiges Werkzeug und ein zentraler Bestandteil des Responsive Web Design. Sie sorgen dafĂŒr, dass sich die Webseiten "responsiv" verhalten und den Ausgabemöglichkeiten des GerĂ€ts optimal anpassen. Die Regeln sind kinderleicht und verstehen sich meistens von selbst. Als Beispiel beachtet ein Desktop-PC die Angabe von min-width: 800px, ein kleineres Smartphone hingegen kann sie problemlos ignorieren. Vor allem wenn bei der Entwicklung einer Webseite der Mobile-First-Ansatz beachtet wird, lassen sich Regeln Schritt fĂŒr Schritt hinzufĂŒgen, ohne dabei die bestehenden Ă€ndern zu mĂŒssen.
@media only screen and (min-device-width : 768px)
and (max-device-width : 1024px) and
(orientation : landscape) {
}
Die obige Regel kommt beispielsweise nur zum Einsatz, wenn der Besucher ein Tablet verwendet und es quer hĂ€lt. Bereits heute gibt es neben orientation (portrait, landscape) weitere nĂŒtzliche Angaben, wie
webkit-device-pixel-ratio: 2 oder resolution: 96dpi fĂŒr die Optimierung auf GerĂ€ten, die mit Bildschirmen mit einer besonders hohen Pixeldichte ausgestattet sind. Auch Typ-Angaben wie screen oder tv werden schon verwendet.
@media (-webkit-min-device-pixel-ratio: 1.5),
(min-resolution: 144dpi){
/* Optimierungen fĂŒr retina / high-res */
}
@media screen and (device-aspect-ratio: 16/9),
screen and (device-aspect-ratio: 16/10) { ... }
@media tv and (scan: progressive) { ... }
Bis zu einem gewissen MaĂ an KomplexitĂ€t lassen sich allerlei Optimierungen mit MediaQueries vornehmen, irgendwann kann allerdings kein Entwickler mehr den Durchblick behalten. Die Anzahl an CSS-Klassen wird unĂŒberschaubar und die Redundanz vieler Angaben steigt, denn mit einem bisschen Copy-and-paste lassen sie sich an vielen Stellen im Code wiederverwenden. Dieses Problem lĂ€sst sich durch CSS-PrĂ€kompilierung mit einem SASS- oder LESS-Compiler schnell vermindern, hĂ€ufig kann sich jedoch der Einsatz eines Grid-Systems als vorteilhafter erweisen.
Ein Grid sorgt fĂŒr die Unterteilung des Layouts in Zeilen und Spalten. Jedes GerĂ€t entscheidet anhand des verfĂŒgbaren Platzes, ob es die Spalten neben- oder untereinander darstellt. Viele Frameworks wie Twitter Bootstrap, Foundation oder Skeleton enthalten ein entsprechendes Werkzeug [2].
Zwar lassen sich komplexe Layouts ebenfalls mit floats und inline-blocks umsetzen, das ist meistens allerdings vergleichsweise aufwendig â gerade dann, wenn unterschiedliche GerĂ€te zu berĂŒcksichtigen sind. AuĂerdem ist es ohne JavaScript nicht möglich, Elemente auf der Webseite anders anzuordnen. Mittlerweile gibt es VorschlĂ€ge fĂŒr flexiblere Alternativen, zu denen die Flexbox und das CSS3 Grid Layout zĂ€hlen.
Alternative AnsÀtze
Was ein display:block macht, sollte jedem Webentwickler bekannt sein. Laut Definition ist block ein Layout-Modus der beschreibt, dass Elemente einen Block bilden â Ă€hnlich p oder dem div-Element. Durch den flex-Modus ergeben sich neue Möglichkeiten, Elemente innerhalb eines Containers auszurichten oder den Abstand zwischen den einzelnen Elementen automatisch zu optimieren. Der Container versucht dabei, die Elemente zu vergröĂern, um den zur VerfĂŒgung stehenden Platz auszunutzen, oder zu verkleinern, um ein Ăberlappen zu verhindern.
Mit einem flex-Container lÀsst sich die Ausrichtung mittels flex-flow: row oder flex-flow: column den Kind-Elementen vererben. Je nachdem, welche Variante verwendet wurde, passt sich der Abstand links und rechts (row) beziehungsweise oben und unten (column) an.
.container {
display: flex;
flex-flow: row;
justify-content: center;
}
Anders als beim Flexbox-Modell ermöglicht das Grid-Layout eine flexible Positionierung von Elementen in Zeilen und Spalten innerhalb eines Containers. Bei RWD bedeutet das, dass sich Elemente optisch je nach Auflösung anders positionieren lassen. Momentan unterstĂŒtzt nur der Internet Explorer (10+) dieses Feature, und es bleibt offen, ob WebKit oder mobile Browser nachziehen.
Die Position eines Elements innerhalb eines Grid-Containers können Entwickler ĂŒber ein Koordinatensystem festlegen:
#container {
display: grid;
}
#element1 {
grid-column: 1;
grid-row: 1
}
#element2 {
grid-column: 3;
grid-row: 1;
}
Umgang mit Bildern
GroĂe Bilder fĂŒr kleine GerĂ€te
Laut aktuellen Statistiken [3], besteht bei einer durchschnittlichen Webseite der gröĂte geladene Anteil mit 62 Prozent aus Bildern. Grund genug, um ein absoluter Performancekiller bei RWD zu sein. Wie optimal in der responsiven Welt mit Bildern umzugehen ist, bleibt heute noch ein ungelöstes RĂ€tsel. Doch eines ist jedem klar: Ein Bild mit hoher Auflösung auf einem kleinen GerĂ€t mit langsamer Verbindung anzuzeigen, ist weder fĂŒr den Besucher noch fĂŒr die Bandbreite eine Lösung.
Im Idealfall sollte je nach Auflösung ein optimiertes Bild dargestellt werden. Das einzige Problem dabei ist, dass es fĂŒr den Server keinen Unterschied macht, wer das Bild gerade anfordert. Selbst eine Abfrage der User Agents, sprich des Browsers, der sich anmeldet, bleibt eine ungĂŒnstige Lösung â vor allem da es im Moment viele unterschiedliche gibt und in Zukunft noch viele weitere hinzukommen. AuĂerdem sagt ein User Agent nur bedingt etwas ĂŒber die GröĂe des Bildschirms und dessen Auflösung aus.
Die Auflösung lĂ€sst sich nicht auf Serverseite ĂŒberprĂŒfen, da sie erst clientseitig, also im Browser, zu ermitteln ist. Als Lösung bietet sich beispielsweise an, ein Cookie mit der Auflösung des GerĂ€ts zu setzen, bevor das erste Bild der Webseite geladen wird. Der nötige Wert lĂ€sst sich anschlieĂend bei der Anfrage fĂŒr das Bild auf dem Server ermitteln. Theoretisch funktioniert dieses Vorgehen [4] ausgesprochen gut, denn das Setzen eines Cookies auf dem Client erfordert kein komplettes Laden der Seite.
In so gut wie jeder Technik gibt es die Möglichkeit, auf bestimmte Dateien wie Bilder zu horchen und die Anfragen so zu verarbeiten, dass sich Bilder dynamisch zuschneiden lassen. Ein Ablauf kann wie folgt beschrieben werden:
- Ein kleiner Code-Schnipsel, der ein Cookie mit Informationen ĂŒber die Auflösung setzt, wird beim Laden der Webseite im Head platziert.
- Der Browser sendet bereits bei der ersten Anfrage eines Bildes den Cookie-Header mit. (Der Bereich im Head wird vor dem Body ausgefĂŒhrt.)
- Der Server routet die Bild-Anfragen (etwa ĂŒber die .htaccess-Datei) an eine bestimmte Datei oder Komponente, die das Cookie ausliest, das Bild verkleinert und anschlieĂend zurĂŒckliefert.
- Die Komponente kĂŒmmert sich zusĂ€tzlich um das Ablegen des zurechtgeschnittenen Bildes im Cache (/image-cache/480/image.jpg), sodass es bei der nĂ€chsten Anfrage sofort zur VerfĂŒgung steht.
Diese Variante hat den Vorteil, dass am bestehenden HTML-Markup nichts zu Àndern ist, allerdings kann sie sehr performanceintensiv sein und sie ist vom Ansatz her nicht ganz responsiv.
Die Responsive Images Community Group [5] verfolgt mit dem Ansatz, verschiedene Bilder fĂŒr verschiedene Auflösungen bereitzustellen, ein weiteres interessantes Konzept. Mit dem neuen picture-Element lĂ€sst sich Ă€hnlich wie im HTML5-Video-Element die Ressource direkt in der HTML-Datei angeben:
<picture>
<source media="(min-width: 1024p)" src="image-hd.jpg">
<source media="(min-width: 480px)" src="image.jpg">
<source src="image-small.jpg">
<img src="image-small.jpg" alt="">
<p>Ein responsives Bild!</p>
</picture>
Apples Vorschlag an das W3C basiert auf Attributen, mit denen Entwickler Bilder steuern können. Wenn auch auf den ersten Blick mit etwas unverstÀndlichen Angaben, besteht das srcset-Attribut aus dem Namen des Bildes, der Pixeldichte und des maximalen Viewports:
<img alt="Ein responsives Bild!"
src="image.jpg"
srcset="image-hd.jpg 2x, image-phone.jpg 100w,
image-phone-HD.jpeg 100w 2x">
Die im Attribut verwendeten Regeln können wie folgt verstanden werden:
- image.jpg: Standartbild
- image-hd.jpg: fĂŒr GerĂ€te mit einer Pixeldichte (pixel ratio) gröĂer als 2
- image-phone.jpg: fĂŒr GerĂ€te mit einem maximalen Viewport von 100w (w steht hier fĂŒr width)
- image-phone-hd.jpg: fĂŒr GerĂ€te mit einem maximalen Viewport von 100w und einer Pixeldichte von höher als 2
Eine reine CSS-Lösung liegt als W3C Editor's Draft ebenfalls vor und wird bereits von Safari 6+ und Chrome 21+ unterstĂŒtzt:
background-image: image-set( "image.jpg" 1x,
"image-hd.jpg" 2x,
"image-druck.jpg" 600dpi );
Letztendlich sollen die neuen Features voraussichtlich mit HTML 5.1 verfĂŒgbar sein, bis dahin ist eine JavaScript-Lösung höchstwahrscheinlich das Beste fĂŒr einen produktiven Einsatz. DafĂŒr bringt zum Beispiel PictureFill [6] eine Reihe von mit data-Attributen versehenen Elementen ins Spiel, die, wenn auch nur mit JavaScript, zum selben Ergebnis fĂŒhren, sprich anhand der Auflösung ein geeignetes Bild laden:
<span data-picture data-alt="Ein responsives Bild!">
<span data-src="image-klein.jpg"></span>
<span data-src="image-medium.jpg" data-media="(min-width: 400px)">
</span>
<span data-src="image-large.jpg" data-media="(min-width: 800px)">
</span>
<!-- Fallback content fĂŒr non-JS Browsers. -->
<noscript>
<img src="image.jpg" alt="Ein normales Bild!">
</noscript>
</span>
Von einer anderen Sichtweise betrachtet, könnte vielleicht ein anderer, nicht von der Webseite abhĂ€ngiger Weg zur Lösung dieses Dilemmas fĂŒhren. Der Browser rendert ein klassisches Bild (zum Beispiel im JPG-Format) nach dem Top-to-bottom-Verfahren, das heiĂt, er baut es von oben nach unten auf. Einen anderen Ansatz verfolgen sogenannte Progressive JPGs: Sie werden erst in einer kleinen Auflösung geladen und dann (progressiv) immer schĂ€rfer. Die Bandbreite profitiert von der Idee nicht, es kann aber die Benutzerfreundlichkeit erhöhen, da sofort â wenn auch unscharf â ein Bild zu sehen ist.
Navigation und Eingaben
Bilder sollten optimiert ausgeliefert werden, und eine weitere Herangehensweise [7] zeigt, dass eine bestimmte Kombination von Auflösung und Kompressionsrate interessante Ergebnisse liefert. Rendert man ein Bild mit der doppelten Auflösung und einer höheren Kompressionsrate, benötigt es zwar weniger Speicher, lÀsst sich aber dennoch auf Bildschirmen mit hoher Auflösung relativ scharf anzeigen.
Das Privileg, mit pixelunabhĂ€ngigen Vektorgrafiken zu arbeiten, blieb bisher den Designern vorbehalten. Mithilfe von SVG-Grafiken (Scalable Vector Graphic) lassen sich derart erstellte Bilder auch im Browser anzeigen. Mit einer kleinen SpeichergröĂe, einer Skalierung ohne QualitĂ€tsverlust und einer perfekten Darstellung â auch auf hochauflösenden Bildschirmen â eignet sich das Format ideal fĂŒr responsive Webseiten. Icon-Fonts sind nur eine von vielen sinnvollen Einsatzmöglichkeiten. Ab Internet Explorer 9 und Android 2.3 können die entsprechenden Browser in den vollen Genuss dieser Technik kommen, fĂŒr den Rest steht ein normales PNG-Bild per JavaScript-Fallback zur Auslieferung bereit:
<img src="bild.svg" onerror="this.onerror=null; this.src='bild.png'">
Auch Frameworks wie Mondernizr [8] oder SVGeezy [9] bieten kleine Helferlein, um mit JavaScript auf die KompatibilitĂ€t prĂŒfen zu können:
if (!Modernizr.svg) {
$(".logo img").attr("src", "images/logo.png");
}
Viele Wege fĂŒhren zum Ziel: Navigation
Eine funktionierende Navigation ist bei RWD essenziell. Der Besucher soll sich mobil, aber auch auf dem Desktop schnell zurechtfinden. Eine einzige Hauptnavigation mit vielen Punkten kann sich negativ auf die Benutzerfreundlichkeit mancher GerĂ€te auswirken. Viele Webseiten wandeln das MenĂŒ auf kleineren GerĂ€ten in Dropdown-Listen um, was bei einer begrenzten Anzahl an Punkten zwar ĂŒbersichtlich sein mag, aber spĂ€testens ab einer tieferen Struktur mit mehreren Ebenen unĂŒbersichtlich wird. Es ist also in den meisten FĂ€llen nicht empfehlenswert, mit Input-Elementen ein Pseudo-MenĂŒ-Control zu erstellen.
Das Beispiel des auf MobilgerĂ€ten zugeklappten MenĂŒs findet sich auf immer mehr Webseiten wieder. Ab einer bestimmten Auflösung verschwindet das MenĂŒ innerhalb eines Liste-Icons und wird erst bei Klick beziehungsweise Touch angezeigt (ein Implementierungsbeispiel ist im Exkurs "Responsive Navigation" [10] zu finden). Diese Art der Umsetzung bringt einige Vorteile, denn es lassen sich mehrere Ebenen ineinander verschachteln, und durch die Implementierung auf zahlreichen Webseiten verstehen sie viele Besucher automatisch. AuĂerdem lĂ€sst sie sich fĂŒr jede Auflösung optimieren, um beispielsweise auf einem Tablet in einer linken Spalte aufzuklappen, wie es native Anwendungen vormachen. Es gibt noch keine Pauschallösung, die in jedem Fall zu 100 Prozent die richtige ist, aber das Rad muss auch nicht neu erfunden werden, denn es haben sich schon viele Entwickler und Designer mit diesen Konzepten auseinandergesetzt [11].
Gut ĂŒberlegt: Eingabefelder und Formulare
Mit vielen Textfeldern und unĂŒbersichtlichem Design bei Formularen ist ein Ausstieg der Nutzer auf mobilen Webseiten garantiert. Deshalb ist es wichtig, sie nicht nur kurz, sondern auch ĂŒbersichtlich zu halten. Beispielsweise lassen sich Textfelder in vielen FĂ€llen viel eleganter mit einer Checkbox, Radio-Buttons oder einer Dropdown-Liste ersetzen.
Bei der Validierung der Eingabe ist es besonders wichtig, dem Besucher sofort einen Hinweis auf fehlerhafte Eingaben zu geben. Beim Absenden des Formulars ist es meistens zu spĂ€t, denn ein Formular ist im Normalfall viel lĂ€nger als ein Smartphone-Bildschirm hoch, was zu unnötiger Verwirrung fĂŒhren kann.
Zahlreiche Frameworks bieten eine groĂe Palette fĂŒr hĂŒbsche Formulare und eine mĂ€chtige Validierung. Als Krönung bringt HTML5 einige Neuerungen mit, wie das require-Attribut fĂŒr Eingabeelemente. Ganz ohne JavaScript erfĂ€hrt der Besucher, dass es sich um ein Pflichtfeld handelt. Auch neue Form-Controls, wie ein number-, email-, range- oder date-Input, sorgen gerade auf mobilen GerĂ€ten fĂŒr neue Interaktionsoptionen. So kann beim Fokussieren eines Datumsfeldes der mobile Browser sofort einen nativen Kalender öffnen, ohne immer auf eine Framework-UI-Komponente wie dem jQuery-Datepicker zurĂŒckgreifen zu mĂŒssen.
Da sie zum Teil nicht auf Touch-GerĂ€te optimiert sind, kann eine lĂ€stige Ăberlappung von anderen Elementen die Folge sein. Bei E-Mail- oder Zahlenfeldern kann sich der Browser ebenso dafĂŒr entscheiden, eine angepasste und optimierte Tastatur anzuzeigen, um dem Besucher Zeichen wie "@" sofort anzeigen zu können.
| date | Ein Control fĂŒr Datumsfelder, welches auf viele mobile Browser den nativen Kalender anzeigt | <input type="date"> |
| datetime | FĂŒr das Datum und Zeit im UTC-Format | <input type="datetime"> |
| datetime-local | FĂŒr das Datum und Zeit unter Verwendung der aktuellen Zeitzone | <input type="datetime-local"> |
| month | Auswahl fĂŒr Monat und Jahr | <input type="month"> |
| time | Auswahl fĂŒr die Zeit | <input type="time"> |
| week | Auswahl fĂŒr Woche und Jahr | <input type="week"> |
| color | Ein Feld fĂŒr die Eingabe von einfachen Farb-Werten (hexadezimal) | <input type="color""> |
| Ein Feld fĂŒr die Validierung von e-Mail Adressen | <input type="email"> | |
| tel | Ein Feld fĂŒr die Validierung von Telefonnummern gegen ein optionales Pattern | <input type="tel"> |
| search | FĂŒr die Suche in einem Datenset (zum Beispiel in einem <datalist> HTML element) | <input type="search"> |
| range | Ein Slider-Element fĂŒr die einfache Auswahl einer Zahl, welcher zwischen zwei Zahlen liegt | <input type="range"> |
| number | Ein Feld, welches nur Zahleneingaben akzeptiert | <input type="number"> |
| url | Ein Feld, welches nur korrekte URLs akzeptiert | <input type="url"> |
Nicht ohne Grund gibt es ab HTML5 zahlreiche neue Input-Felder (Tab. 1)
Testen, Testen, Testen!
Eine responsive Webseite lĂ€sst sich auf vielerlei Arten testen â im einfachsten Fall, indem das Browser-Fenster gröĂer und kleiner gezogen wird. Das lĂ€stige Ăndern des Browser-Fensters lĂ€sst sich durch Werkzeuge wie die Chrome-Entwicklertools oder Online-Tools wie responsinator [12], responsivepx [13] oder screenfly [14] einfach ersetzen, inklusive vordefinierter Breakpoints fĂŒr MediaQueries. Es ist aber zu beachten, dass die Online-Tools meist nur mit IFrame-Einbettung oder mit ergĂ€nzenden Scrollbalken arbeiten und somit nicht hundertprozentig pixelgenau sind. Die Simulation kann bei der Entwicklung von enormen Vorteil sein und eine wahre Zeitersparnis darstellen, trotzdem sollte das Ergebnis am Ende noch ausgiebig auf den jeweiligen GerĂ€ten getestet werden.
Fazit
Mit vielen Vorteilen, aber auch deutlichem Mehraufwand fĂŒr Entwickler, prĂ€sentiert sich RWD als momentaner Hype in der Webszene. Mithilfe der richtigen Werkzeuge gestaltet sich das Erstellen einer responsiven Webseite angenehm unkompliziert. Eine eindeutige Empfehlung bei der Entscheidung fĂŒr das richtige Frameworks gibt es allerdings nicht. Es ist also je nach Anwendungsfall zu ĂŒberlegen, welches die meisten Vorteile mitbringt, welche die ideale Lösungen fĂŒr Bilder ist und wie die Navigationbenutzerfreundlich bleibt. Grundlegende Patterns wie jene einer aufklappbaren Navigation und der HTML5-Input-Formulare sind mittlerweile weit verbreitet und lassen sich meist ohne groĂe Bedenken einsetzen. Die Kosten-Nutzen-Analyse ist und bleibt momentan als Entscheidungshilfe unschlagbar und dient vielen Entwicklern und Unternehmen als Richtlinie.
Roberto Bez [15]
ist passionierter Webentwickler und begeistert von neuen Technologien, die er versucht, in die tÀgliche Anwendungsentwicklung miteinzubringen.
Exkurs: Responsive Navigation
Die hinterlegte Datei [16] zeigt eine Beispielanwendung mit responsiver Navigation. Das Navigationselement ist wie folgt aufgebaut:
<header id="header">
<h1>Responsive Nav</h1>
<a class="nav-btn" id="nav-open-btn" href="#nav"></a>
</header>
<nav id="nav">
<a class="close-btn" id="nav-close-btn" href="#top"></a>
<ul>
<li>Willkommen</li>
<li>Ăber mich</li>
<li>Kontakt</li>
</ul>
</nav>
Mit den entsprechenden Anweisungen im CSS stellt sich FlexibilitÀt ein:
body
{
margin: 0;
padding: 0;
color: White;
font-family: Verdana;
}
#header
{
background-color: #343434;
padding: 20px;
text-align: center;
}
#nav
{
width: 100%;
background-color: #343434;
border-bottom: 3px solid black;
}
#nav-open-btn,
#nav-close-btn
{
position: absolute;
right: 10px;
top: 10px;
background-image: url(nav-icon.png);
display: block;
width: 20px;
height: 20px;
display: none;
}
#nav ul
{
list-style: none;
padding: 10px;
margin: 0;
text-align: center;
}
#nav ul li
{
display: inline-block;
padding: 5px;
}
#nav ul li:hover, .selected
{
background-color: #26a5e0;
}
@media (max-width: 480px)
{
#nav {
position: absolute;
top: 0px;
}
#nav ul {
margin-top: 25px;
}
#nav ul li
{
display: block;
}
/* Der Link zum öffnen/schlieĂen des MenĂŒs Ă€ndern den Anker #nav */
#nav:not(:target)
{
display: none;
}
#nav-open-btn, #nav-close-btn
{
display: block;
}
} (jul [17])
URL dieses Artikels:
https://www.heise.de/-2165715
Links in diesem Artikel:
[1] https://www.heise.de/hintergrund/Die-Theorie-der-responsiven-Webseiten-2123587.html
[2] http://devangelist.de/css-responsive-frameworks/
[3] http://httparchive.org/interesting.php#bytesperpage
[4] http://adaptive-images.com/
[5] http://responsiveimages.org/
[6] https://github.com/scottjehl/picturefill
[7] http://www.netvlies.nl/blog/design-interactie/retina-revolution
[8] http://modernizr.com/docs/
[9] http://benhowdle.im/svgeezy/
[10] http://www.heise.de/developer/artikel/Responsive-Webseiten-gestalten-2165715.html?artikelseite=5
[11] http://bradfrost.github.io/this-is-%20responsive/patterns.html#navigation
[12] http://www.responsinator.com/
[13] http://responsivepx.com/
[14] http://quirktools.com/screenfly/
[15] http://devangelist.de/
[16] https://www.heise.de/downloads/18/1/2/0/4/5/7/0/nav.zip
[17] mailto:jul@heise.de
Copyright © 2014 Heise Medien