image caption fly-out: Animierte Bildbeschriftungen nur mit HTML & CSS

Im World Wide Web stösst man immer wieder auf Bild- und Text-Komponenten (z.B. Teaser), die in spezifischer Weise mit dem Besucher interagieren: Im unteren Bereich wird das Bild von einer Text-Zeile überlagert, die beim Überfahren mit der Maus hochrollt und weiteren Text freigibt.

Oftmals kommen dabei schwergewichtige Javascript-Lösungen und aberwitzige Berechnungen zum Einsatz, doch ist eine Umsetzung ausschließlich mit HTML und CSS ebenfalls möglich.

Das Ziel

Ich bin mir nicht sicher, ob fly-out die korrekte Bezeichnung ist (und nehme entsprechende Hinweise aus Kommentaren gerne zur Kenntnis), aber den Effekt dürften viele schon gesehen haben:

  • ein Bild wird im unteren Bereich von einem (einzeiligen) Text nebst Hintergrund überlagert. Die Bildunterschrift liegt also auf dem Bild.
  • wird der Mauszeiger über das Bild bewegt, so rollt der überlagernde Text-Bereich nach oben und gibt weitere Text-Passagen frei.
  • wird der Mauszeiger aus dem Bild bewegt, fällt der Text wieder auf seine ursprüngliche Höhe zusammen.

Ein Bild sagt mehr als tausend Worte, daher hier ein Beispiel für das zu erreichende Ziel (bitte Mauszeiger über das Bild bewegen).

Scan einer Postkarte mit historischer Ansicht der Dahlen-Mühle

Historische Ansichtskarte aus Sevelen

Die Aufnahme zeigt die Dahlen-Mühle aus Sicht des heutigen, neuen Sevelener Friedhofs. Es wurde ca. 1930 für eine Postkarte aus Sevelen verwendet.

Der Weg

Die Lösung basiert – wie bereits angekündigt – auf reinem HTML-Markup und Styling über CSS-Regeln. Zur semantischen Abbildung des Konstrukts bietet sich das mit HTML 5 neu eingeführte figure-Element nebst seines Kind-Elements figcaption an. Notwendig ist dies allerdings nicht, auch andere Lösungen mit <div> oder <dl>, <dt> und <dd> sind möglich.

HTML Mark-Up


<figure>
<img src="https://placehold.it/600x300" alt="placeholder">
<figcaption>
<h1>Bildunterschrift</h1>
<p>Weiterführender Text zum Bild
(kann auch mehrere Paragraphen enthalten)</p>
</figcaption>
</figure>

Das reine HTML führt zu dem unten abgebildeten Ergebnis. Da noch spezifisches Styling fehlt, kommen die Standardwerte des jweiligen Browsers zum Einsatz.

Cascading Stylesheets

Um unserem Ziel näher zu kommen, wird mit dem grund­sätz­lichen Styling begonnen:


figure {
position: relative;
width: 600px;
overflow: hidden;
line-height: 0;
}
figure img {
max-width: 100%;
}
figure figcaption {
position: absolute;
bottom: 0;
width: 90%;
padding: 0 5%;
background-color: rgba(0,0,0,0.8);
color: white;
}

  • das figure-Element bekommt eine definierte Breite, an der sich die Inhalte (also Bild und Text) orientieren. Außerdem wird die Zeilenhöhe (line-height) auf 0 gesetzt, um unerwünschten Abständen durch Umbrüche im HTML entgegenzuwirken.
  • das figcaption-Element bekommt 5% Innenabstand (padding) zu beiden Seiten, damit der enthaltene Text nicht an die Ränder stösst. Es wird außerdem am unteren Rand ausgerichtet (bottom).
  • Vorder- und Hintergrund-Farbe des Overlays werden definiert.

Optisch ist das erreichte Zwischenergebnis schon recht nahe am geplanten Ziel, aber noch bewegt sich nichts. Ändern soll dies Verwendung der transition-Vorschrift auf dem max-height-Attribut des figcaption-Elements. Ziel ist es, daß im Ursprungszustand max-height für die Darstellung der Überschrift (<h1>) ausreicht und diese Beschränkung im hover-Zustand aufgehoben wird.

Es gilt nun also die notwendige (Achtung: Kein Widerspruch) minimale Maximal-Höhe zu finden, welche sich aus der Höhe (height) des h1-Elementes zzgl. seiner Abstände und Rahmen ermitteln lässt. Damit das Ganze nicht in einer Pixel-Orgie ausartet und auch im Rahmen eines Responsive Design funktioniert, empfehle ich die Verwendung von em, also der relativen Zeichengröße:


figure figcaption h1 {
font-size: 2em;
line-height: 1em;
padding: 0.25em 0;
margin: 0;
}

Zur Erklärung:

  • zunächst wird die Schriftgröße auf 2em gesetzt, was einer Verdoppelung zur umgebenden Schriftgröße entspricht
  • desweiteren wird die Zeilenhöhe auf die aktuelle Schriftgröße gesetzt. Der Wert 1em bezieht sich auf die aktuell gültige Schriftgröße, welche durch die vorherige Zeile auf das Doppelte der normalen Schriftgröße gesetzt wurde.
  • außerdem bekommt die Überschrift oberhalb und unterhalb etwas Innenabstand, um atmen zu können. Auch für padding gilt, daß em in Relation zur aktuellen Schriftgröße gesehen werden muß.
  • das explizite Setzen des Außenabstands (margin) auf 0 soll die Anwendung von Browers-Vorgaben unterdrücken. Andernfalls würde z.B. Mozilla Firefox hier einen Standardwert von 0,67em anwenden.

Damit hat das h1-Element jetzt – von außen betrachtet – eine Höhe von 3em (2em + 2 × 0,25 × 2em). Dies ist der initiale Wert für das max-height-Attribut des figcaption-Elements. Er wird dafür sorgen, daß im Ursprungszustand nur die einzeilige Überschrift sichtbar sein wird. Gleichzeitig wird diese Beschränkung aufgehoben, sobald der Mauszeiger das figure-Element betritt.

Damit das Ganze nicht schlagartig, sondern schön smooth ’n easy passiert, wenden wir die CSS-Eigenschaft transition auf das max-height-Attribut an. Es ergibt sich folgende CSS-Ergänzung:


figure figcaption {
max-height: 3em;
transition: max-height 1s ease-in-out;
}
figure:hover figcaption {
max-height: 100%;
}

Erläuterung:

  • max-height: 3em ist wie oben erläutert der initiale Wert für die maximale Höhe des Text-Overlays.
  • transition: max-height sorgt dafür, daß bei Veränderung des max-height-Wertes zwischen Soll- und Ist-Wert interpoliert wird. Die Dauer bis zum Erreichen des Soll-Wertes wird auf 1 Sekunde (1s) gesetzt. Die Veränderung soll dabei nicht linear, sondern mit Beschleunigung und Verzögerung erfolgen (ease-in-out)
  • figure:hover figcaption definiert das Verhalten des figcaption-Elementes, sobald der Mauszeiger sich über dem umgebenden figure-Element befindet. Abgebildet wird dies durch die CSS-Pseudoklasse :hover am entsprechenden Element.

Damit haben wir unser Ziel erreicht: Animierte Bildbeschriftungen nur mit HTML und CSS.

placeholder

Bildunterschrift

Weiterführender Text zum Bild
(kann auch mehrere Paragraphen enthalten)

Das Fazit

Die hier vorgestellte Lösung stellt eine Alternative zu Ansätzen mit Javascript dar und erlaubt ein Auskommen ohne zusätzliche Bibliotheken wie jQuery. Durch den Fokus auf Standards wie HTML(5) und CSS(3) werden Inkompatibilitäten vermieden und gleichzeitig das Potential moderner Browser ausgenutzt.

Gleichwohl ist sie nicht frei von Nachteilen, die hier kurz aufgeführt sind:

  • Geräte ohne Mauszeiger, wie Mobiltelefone und Tablet-PCs, werden den ergänzenden Text nicht zu sehen bekommen. Bei der Formulierung ist also darauf zu achten, daß bereits die Überschrift ausreichend Informationen bereitstellt und sich die weiterführenden Angaben auf anderem Wege ermitteln lassen.
    Dies gilt allerdings auch für Javascript-Lösungen gleichermaßen.
  • Versionen des Internet Explorers bis einschließlich Version 9 unterstützen die CSS-Eigenschaft transition nicht. Bei diesen Versionen wird das fly-out also schlagartig erscheinen (s.a. http://caniuse.com).
  • das Einfahren des Overlays beim Verlassen des figure-Elementes geschieht mit einer gewissen Verzögerung. Grund hierfür ist, daß die Transition für max-height bei 100% startet, das Overlay aber i.d.R. nicht die volle Höhe des figure-Elementes einnimmt. Die ersten Momente der Höhenreduktion sind daher nicht sichtbar.

Bzgl. des letzten Punktes haben Experimente mit height statt max-height nicht zum Erfolg geführt. Ein Wechsel von einer definierten Höhe (z.B. height: 3em) auf den automatisch ermittelten Wert (height: auto) wurde nicht via transition interpoliert und erfolgte sprunghaft.

Abschließend noch ein Hinweis zur Hintergrund-Farbe des Overlays: CSS3-Farben mit rgba (also Farbe + Transparenz) werden noch nicht von allen Browsern unterstützt. Alternativ kann figcaption darum ein transparentes Bild (PNG) als Hintergrund (background-image) zugewiesen werden. Vermeiden sollte man allerdings opacity, da dies sich auch auf die Schrift auswirkt.

  1. Hermann sagt:

    Eine an sich schöne Sache und eine tolle Fleißarbeit!
    3 Fragen bleiben:

    1.) Ist es möglich, das Ganze SO zu programmieren, dass sich die Bildgröße fließend ist und sich wie bei Bildern in responsive Templates proportional verkleinern, entsprechend der Fensterbreite, statt einer fixen Größe?
    Wenn alle anderen Bilder flexibel sind, sieht ein „störrisches“ fixes Bild dazwischen vor allem auch auf dem Handy später wahrscheinlich suboptimal aus?!

    2.) In der historischen Ansichtskarte wird der beschreibende Text im Bild automatisch umbrochen. Bei mir schiebt sich die Textzeile ohne Umbruch, wenn sie breiter wird als die definierte Bildbreite, in sich selbst zusammen, statt in einer 2. Zeile weiter zu laufen.

    3.) Das H1-Element soll in jeder Seite eigentlich nur je 1 X vorkommen. Gibt es eine Lösung, den Headline-Text anders, jedoch ebenfalls möglichst SEO-wirksam vorzuformatieren (z. B. bei mehreren Bildern mit ausklappbarer figcaption auf einer Seite)?

    Danke im Voraus für die Antwort!

  2. Christoph sagt:

    Hallo Hermann, entschuldige bitte die Verzögerung meiner Antwort:

    1.) Ist es möglich, das Ganze SO zu programmieren, dass sich die Bildgröße fließend ist und sich wie bei Bildern in responsive Templates proportional verkleinern, entsprechend der Fensterbreite, statt einer fixen Größe?

    Ja. Die Angabe von 600px ist nur beispielhaft. Tatsächlich kann hier auch eine relative Größe angegeben werden, so daß das <figure>-Element seinen Anteil an der verfügbaren Breite einnimmt.

    2.) In der historischen Ansichtskarte wird der beschreibende Text im Bild automatisch umbrochen. Bei mir schiebt sich die Textzeile ohne Umbruch, wenn sie breiter wird als die definierte Bildbreite, in sich selbst zusammen,…

    Dazu kann ich ad hoc nichts sagen. Vielleicht machst Du mal ein Beispiel bei JSFiddle auf.

    3.) Das H1-Element soll in jeder Seite eigentlich nur je 1 X vorkommen. Gibt es eine Lösung, den Headline-Text anders, jedoch ebenfalls möglichst SEO-wirksam vorzuformatieren (z. B. bei mehreren Bildern mit ausklappbarer figcaption auf einer Seite)?

    Es kann jedes andere Element verwendet werden, welches an dieser Stelle zulässig ist, z.B. <p> oder <header>. Auch eine mehrfache Verwendung von <h1> ist in HTML5 unproblematisch, wenn es in einer eigenen <section> vorkommt.

Kommentar hinterlassen