5202

ein Blog über technische Fragen zu Blogger

HTML5 Fader ohne Javascript

von
Vor langer Zeit habe ich hier auf 5202 einen reinen CSS-Fader vorgestellt.

Der war a bisserl wackelig auf den Beinen, vieles hat gefehlt und deswegen habe ich einem lieben Leser versprochen, bei Gelegenheit völlig neu drüber nachzudenken

Tröööt ... heute das Ergebnis davon - ein grundsolider HTML5 Fader:

HTML5

Freunde, nicht nur in der Politik beim Euro wird geschummelt, sondern auch im Webdesign. Was habe sie uns nicht alles über HTML5 versprochen und wie-einfach-damit-das-Web-wird.

Was eine glatte Lüge ist - mit HTML5 sind die Inkompatibilitäten in den Browser schlimmer den je, Specs werden von den Browserhersteller wohl nur noch als nice-to-have gesehen und alle kochen inzwischen ihr eigenes Süppchen.

Ich habe stundenlang tagelang über Probleme gesessen, weil immer ein Browser ein völlig unerwartetes Ergebnis gezeigt hat - teilweise sogar der gleiche im anderen OS - und alles zusammen bin ich der Meinung, das HTML5 nach fünf Jahren Entwicklung schon a bisserl ausgereifter hätte sein können ... aber das ist die Zukunft :=(.

Features

Mein Ziel war es einen stabilen Fader mit reiner CSS zu bauen, ohne Javascript. Nicht weil Javascript böse ist oder so, sondern weil ich glaube, das CSS für solche Aufgaben [in naher Zukunft] völlig ausreicht.

Ihr könnt damit Bilder beliebiger Größe zeigen, die Bilder werden automatisch mittig zentriert.

Der Fader hat außerdem einen sauberen 'vorwärts/rückwärts' Schalter, eine Navigation über die Position der Bilder und integrierte Untertitel.

Post in zwei Etappen

Die Skizze selber hat einige [Un]Tiefen - ich lass mir deshalb Zeit beim schreiben und lege die Beschreibung auf zwei Posts an.

Die Skizze - HTML

In HTML5 gibt es eine ganze Reihe von neuen semantischen Tags für bestimmte Aufgaben. Für Bilder, die nicht unmittelbar in einem Text eingebunden sind, ist das etwa das figure Tag.

Innerhalb dieses Tags können Bilder, Grafiken, Texte whatever liegen, die teilweise wieder eigene Tags haben - für 'Untertitel' wäre das etwa das figcaption Element.

Praktisch schaut das für ein Bild nun so aus - innerhalb eines <figure> liegt ein <img> Tag mit der Bildquelle und ganz am Ende von dem Tag liegt der 'Untertitel' in einem <figcaption> Tag:
<figure>
   <img src="http://goo.gl/ruxDD"/>
   <figcaption>Italia</figcaption>
</figure>
In HTML5 muss das <figcaption> Tag übrigens am unteren Ende des <figure> Tags liegen, sonst springt ein Fehlerteufel aus dem Bildschirm und frisst euch auf.
Die Navigation
Die kleine Navigationsleiste unter den Bilder ist mit dem <nav> Tag gebaut und innerhalb des Tags liegen neun <span> Container:
<nav>
 <span></span>
 <span></span>
 <span></span>
 <span></span>
 <span></span>
 <span></span>
 <span></span>
 <span></span>
 <span></span>
 </nav>
Das ist an HTML alles, den Rest der Navigation machen wir mit CSS.
Der Schalter
Das Vorwärts/Rückwärts vom Fader bauen wir mit einem alten Bekannten, einem HTML Schalter aus Radio Button Elemente - dazu nehmen wir neun <input> Tags und wrappern die einzelnen <figure> Tags jeweils in ein dazugehöriges Label. Damit das nicht so lang wird, schreibe ich das jetzt nur für _ein_ <input> Tag plus einem Label:
 <input id="box1" name="nav" checked="checked" type="radio" /> 
// weitere input Elemente
<div class=holder">
  <label>
    <figure>
       <img src="http://goo.gl/ruxDD"/>
       <figcaption>Italia</figcaption>
    </figure>
  </label>
//weitere Label
</div>
Das ist nur das HTML für das erste Element - den vollständigen Code findet ihr im Download.

Das wäre an HTML alles ... der Fader ist damit einfach, logisch und semantisch korrekt aufgebaut.

CSS - Vorwärts und Rückwärts

Ich fange in der CSS gleich mit dem schwersten an, nämlich dem vorwärts/rückwärts Schalter. Der ist über zwei Pseudoelemente gemacht, nämlich 'rückwärts' mit ::before, 'vorwärts' mit ::after.

Schauen wir uns zuerst 'vorwärts' an:
label::after {
    background: none repeat scroll 0 0 #f0f0f0;
    content:">";
    display: block;
    width: 70px; 
    height: 70px;
    border-radius: 35px;
    top: 260px;
    line-height: 70px;
    font-size: 40px;
    left: 780px;
    position: absolute;
    z-index: 1;
    border-bottom: 1px dashed rgba(0,0,0,0.1);
    opacity: .01;
}
Die 'runde' Navigation wird mit CSS und nicht mit Grafik gemacht - alle 'Vorwärts' Schalter zusammen bekommen den gleichen z-Index, nämlich 1. Mit Klick auf ein 'Element' wird das jeweils nächste Bild eingeblendet, aber ....

Zweiter Schritt:

Alle neun Pseudoelemente liegen nun übereinander, das letzte Element ist das oberste. Das wollen wir natürlich nicht, sondern es soll nur das jeweils nächste Element in der Reihe oben liegen und das machen wir mit einem Trick:
#box1:checked ~ .holder label:nth-of-type(2)::after,
#box2:checked ~ .holder label:nth-of-type(3)::after,
#box3:checked ~ .holder label:nth-of-type(4)::after,
#box4:checked ~ .holder label:nth-of-type(5)::after,
#box5:checked ~ .holder label:nth-of-type(6)::after,
#box6:checked ~ .holder label:nth-of-type(7)::after,
#box7:checked ~ .holder label:nth-of-type(8)::after,
#box8:checked ~ .holder label:nth-of-type(9)::after{
z-index: 10;
}
Mit jedem 'Klick' geben wir dem nächsten Element den z-Index 10 und machen es damit zum obersten Element ... auf die Art und Weise können wir vom ersten bis zum letzten Element sauber durchklicken - das wäre gelöst!
Rückwärts Klicken
Viel schwieriger ist die 'rückwärts' Navigation. Wir geben der Navigation zuerst a bisserl Style:
label:before{
    background: none repeat scroll 0 0 #f0f0f0;
    content: "<";
    display: block;
    width: 70px; 
    height: 70px;
    line-height: 70px;
    border-radius: 35px;
    font-size: 40px;
    left: -80px;
    top: 260px;
    position: absolute;
    opacity: .01;
}
Beachtet, das wir hier _keinen_ z-Index vergeben. Den geben wir nun jedem Pseudoelement einzeln und zwar in aufsteigender Reihenfolge:
label:nth-of-type(1):before {
z-index: 10;
}
label:nth-of-type(2):before {
z-index: 11;
}
label:nth-of-type(3):before {
z-index: 12;
}
label:nth-of-type(4):before {
z-index: 13;
}
label:nth-of-type(5):before {
z-index: 14;
}
label:nth-of-type(6):before {
z-index: 15;
}
label:nth-of-type(7):before {
z-index: 16;
}
label:nth-of-type(8):before {
z-index: 17;
}
label:nth-of-type(9):before {
z-index: 18;
}
Das neunte Element liegt ganz oben, die anderen darunter ... das könnte man eigentlich als Sortierung nehmen, wenn es den IE nicht gäbe der das nur mit ordentlichem z-Index versteht.

Egal - mit Klick 'rückwärts' wird nun dem jeweils nächstem Element der z-Index 1 gegeben und damit 'rutscht' das Element eins unter das vorhergehende.
#box1:checked ~ .holder label:not(:nth-of-type(1)):before,
#box2:checked ~ .holder label:not(:nth-of-type(1)):before,
#box3:checked ~ .holder label:not(:nth-of-type(2)):before,
#box4:checked ~ .holder label:not(:nth-of-type(3)):before,
#box5:checked ~ .holder label:not(:nth-of-type(4)):before,
#box6:checked ~ .holder label:not(:nth-of-type(5)):before,
#box7:checked ~ .holder label:not(:nth-of-type(6)):before,
#box8:checked ~ .holder label:not(:nth-of-type(7)):before,
#box9:checked ~ .holder label:not(:nth-of-type(8)):before {
z-index: 1;
}
Das funktioniert stabil mit beliebig vielen Elementen mit allen richtigen Browsern und im IE ab 8+.

Ende Teil 1- hier ist die Fortsetzung