Bilder im Internet/Bildwechsler

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Meist werden Bilder nicht nur einzeln, sondern zusammen mit anderen Fotos in einer Bildergalerie präsentiert. Bildergalerien sind immer ein Kompromiss zwischen den Wünschen möglichst viele Bilder auf einmal und in einem bestimmten Bild viele Details anzuzeigen. Deshalb gibt es oft einen Auswahl­mechanismus, damit Bilder in einer Vorschauansicht (engl. thumbnail für daumennagelgroße Ansicht) präsentiert und auf Wunsch auch in einer Großansicht angezeigt werden können.

In diesem Kapitel lernen Sie, wie Sie Bildergalerien mit HTML und CSS gestalten können. Zusätzlich wird ein wenig JavaScript verwendet, um als progressive enhancement (engl. für „schrittweise Verbesserung“) weitere Bedienfunktionen anzubieten.

Lightbox

Im Webdesign ist ein Lightbox-Popup ein Fenster-Overlay, das oben auf einer Webseite erscheint und einen Teil des Inhalts der Seite verdeckt. Wenn ein Popup erscheint, wird der Hintergrund oft abgeblendet und deaktiviert, so dass die Besucher der Website nicht mit anderen Inhalten der Website interagieren können. Dies lenkt die Aufmerksamkeit auf die Lightbox selbst.

Unser Projekt ist eine Bildergalerie, die bei einem Klick auf ein Bild eine Lightbox als Großansicht öffnet, die dann mit JavaScript als progressive enhancement Bedienelemente erhält, um je nach Wunsch des Benutzers

  • eine weitere Auswahl durch den Nutzer
  • ein Verlassen der Lightbox

ermöglichen.

Thumbnail und Großansicht

Bereits im Kapitel Bilder_im_Internet/Formate_und_Größen wurde die Frage nach der richtigen Größe gestellt:

Du musst zwei Bilddateien erstellen.

  • Thumbnails sollten maximal 20 kB groß sein, damit eine Seite mit vielen Vorschaubildern trotzdem schnell geladen wird.
  • Für die große Darstellung sollte das Bild in guter Qualität gespeichert werden. Dabei kann es sich anbieten, Höhe und Breite doppelt so groß zu machen wie das Bild dargestellt werden soll, aber hohe Kompression zu wählen. Moderne Formate wie WebP werden von allen Browsern genutzt.

HTML-Struktur

In diesem Beispiel soll durch den Klick auf ein Vorschaubild eine Großansicht geöffnet werden. Da es in JavaScript nicht möglich ist, auf Unterseiten oder das Dateiverzeichnis des Servers zuzugreifen, sollten die Bilder (oder deren URLs) schon auf der Webseite notiert sein. Dies erreichen wir durch einen Link, der auf den URL der Großansicht verweist:

Lightbox mit Schließen-Button ansehen …
<section id="peru" class="gallery">  
  <h2>Peru 2007</h2>

  <a href="peru-3.jpg">
  	<img src="peru-3-sm.jpg" alt="Peru 2007: Machu Picchu">
  </a>  
  <a href="peru-4.jpg">
  	<img src="peru-4-sm.jpg" alt="Peru 2007: Machu Picchu - Lamas in den Ruinen">
  </a>  
  <a href="peru-5.jpg">
  	<img src="peru-5-sm.jpg" alt="Peru 2007: Uros-Inseln im Titicaca-See">
  </a> 
  ...
</section>

Dieses HTML funktioniert bereits ohne JavaScript:

Das im img notierte kleine Bild wird angezeigt. Bei einem Klick darauf wird das im a-Element referenzierte große Bild geladen und im Browser angezeigt. So wird das im letzten Kapitel erwähnte Standardverhalten der HTML-Elemente genutzt. Zurück geht es mit der Zurück-Button des Browsers.

Diese Struktur dient auch Fallback, falls das im Folgenden erklärte JavaScript wegen schlechter Übertragungsraten nicht geladen werden könnte.

Beachten Sie: Auf den Einsatz von Klassen für thumbnails und die Großansichten wurde verzichtet. Über .gallery a bzw. .gallery img kann jedes Element mit CSS oder JavaScript selektiert werden.

dialog-Element

Unser Beispiel wird nun erweitert. Für die Lightbox wird ein (vorerst nicht sichtbares) dialog-Element in der gallery notiert:

Lightbox mit Schließen-Button ansehen …
<section id="peru" class="gallery">
  <h2>Peru 2007</h2>
  <a href="Peru-1.jpg">
    <img src="Peru-1-sm.jpg" alt="Peru 2007: Cusco - Blick auf Ausangate">
  </a>  
  ……
</section>
	<dialog id="lightbox">
		<figure>
			<img src="" alt="">
			<figcaption></figcaption>
		</figure>
		<button id="close-dialog">Schließen</button>
	</dialog>

Früher wurden für eine Lightbox zwei div-Elemente verwendet - eins für den Inhalt aus oberster Ebene - ein zweites um den Inhalt darunter abzudecken. Das dialog-Element hat demgegenüber eine semantische Bedeutung mit der role="dialog" und in seinem Standardverhalten mehrere Vorteile:

  • der Fokus springt bei Tastaturbedienung automatisch in den geöffneten Dialog
  • der Dialog ist automatisch im Top-Layer‎ angelegt - ohne CSS-Festlegungen
  • mit CSS kann ein ::backdrop-Pseudoelement angelegt werden, das den Inhaltsbereich verdeckt und inaktiv werden lässt; ein so genannter modaler Dialog.

Die open-ui.org schlägt vor, dass Öffnen und Schließen auch durch entsprechende invoketarget-Attribute bereits im HTML erledigt werden. Daurch könnte man zukünftig einige Zeilen JavaScript sparen.

Die müssen wir bis jetzt aber im Script notieren:

Öffnen mit JavaScript

Mit einem Script soll die im href-Attribut notierte URL des großen Bilds für eine Darstellung innerhalb der Webseite in einem modalen Fenster genutzt werden.

Großansicht mit JS ansehen …
  document.querySelector('.gallery').addEventListener('click',function (evt) {
    evt.preventDefault();
		let element = event.target;
		let parentURL = element.parentNode.href;
		let imgAlt = event.target.alt;
		let img = document.querySelector('#lightbox img');
		img.src = parentURL;
		img.alt = imgAlt;
		lightbox.showModal();
  });
 
  document.getElementById('close-dialog').addEventListener('click', () => {
			lightbox.close();
		});

Nach den Regeln des unobtrusive JavaScript wird das Script nicht mit dem HTML vermischt, sondern im head notiert.

Mit AddEventHandler wird dem angeklickten Element eine Funktion zugewiesen.

Diese Funktion …

  1. verhindert mit Event.preventDefault das Aufrufen des Links
  2. ermittelt das auslösende Element (ein Bild)
  3. ermittelt mit parentNode das Elternelement des Bilds (das a-Element), liest die URL des href-Attributs aus und …
  4. setzt diese in das src-Attribut des Bilds im Dialog-Element.
  5. Entsprechend wird das alt-Attribut (wieder)verwertet.
  6. Dann wird mit showModal() die Lightbox sichtbar gemacht.
Beachten Sie: Wie in Bildunterschrift vs. Bildbeschreibung beschrieben, sollte im Allgemeinen der alt-Text nicht für die Bildunterschrift verwendet werden. Hier wurde aus Gründen der Vereinfachung darauf verzichtet.

::backdrop als Zwischenebene

Das ::backdrop-Pseudo-Element ist eine Box in der Größe des Viewports, die unmittelbar unter jedem Element gerendert wird, das in der obersten Ebene dargestellt wird. Sie legt sich nun zwischen dialog-Element und den eigentlichen Inhalten der Webseite.

::backdrop ansehen …
dialog::backdrop {
  background-color: #337599;
  opacity:0.5;
}

Durch diesen modalen Dialog wird der Nutzer gezwungen, sich auf die Großansicht und die dort angebotenen Funktionen zu konzentrieren. Erst mit dem Schließen des modalen Dialogs kehrt er zur Webseite zurück.

Script mit Steuerung

Normalerweise klickt man ja nicht die Großansicht wieder weg, um dann das nächste Bild in Großansicht zu zeigen.

Alle Bilder sind ja als thumbnail in einer section notiert. Falls die section mehr Bilder enthält, soll durch eingeblendete Pfeile ermöglicht werden, dass man weiter (oder zurück) klicken kann (Kein links-Pfeil beim 1., kein weiter-Pfeil beim letzten).

Buttons zum Bedienen

Diese Bedienflächen verlinken nicht auf andere Seiten, sind also keine Links. Da erkennbar sein soll, wenn ein Nutzer diese Bedienfelder mit der Maus oder Tastatur angewählt hat, verwendet man button-Elemente und keine span- oder divs.

Diese Buttons - wie auch das dialog-Element - werden im Normalzustand nicht benötigt und deshalb vom Script erst bei Bedarf erzeugt:

Steuerung-Buttons und dialog-Container erzeugen ansehen …
	const
	// selektiert alle Bilder, die Kindelemente eines a-Elements sind
		allPics = document.querySelectorAll(".gallery a > img"),
		caption = document.createElement("figcaption"),
		close = document.createElement("button"),
		lightbox = document.createElement("dialog"),
		figure = document.createElement("figure"),
		full = document.createElement("img"),
		next = document.createElement("button"),
		prev = document.createElement("button");
	// aktuell anzuzeigendes Bild aus der Liste
	let currentPic = 0;

Zu Beginn des Scripts werden die benötigten Variablen deklariert:

  • allPics selektiert mit querySelectorAll alle Bilder, die Kindelemente eines a-Elements sind
  • figure ist ein dynamisch erzeugtes dialog-Element
  • figure ist ein dynamisch erzeugtes figure-Element, das ein img- ud ein figcaption-Element erhält
  • close, next und prev sind die zu erzeugenden Buttons

Da sich diese während des Programmablaufs nicht ändern, werden sie mit const deklariert.

Die Variable currentPic ist ein Zähler für das jeweilige Bild in der allPics-Liste und wird anfangs auf 0 gesetzt, um das erste Bild anzuzeigen. Da sich diese Variable während des Programmablaufs ändert, wird sie mit let deklariert.

So werden nun die Buttons, aber auch ein dialog-Element als Fullview-Container erzeugt.

Wechsel-Mechanismus

Sobald die Bildergalerie angeklickt wird, soll der Nutzer mit den Buttons zu den einzelnen Bildern vor- und zurückgehen können. Dabei soll -anders als im oberen Beispiel - nicht bei jedem Klick wieder die Klasse current neu gesetzt, sondern einfach die URL der Großansicht in das src-Attribut des img-Elements eingesetzt werden.


Wechselmechanismus ansehen …
	document.addEventListener('click', evt => {

		allPics.forEach((element, index) => {
			if (evt.target == element || evt.target == element.parentNode) {
				currentPic = index;
				lightbox.showModal();
			}
		});
Nun erhält nicht jedes Bild einzeln, sodnern das gesamte Dokumnet einen addEventListener, der bei einem Klick mit einer Pfeilfunktion eine Funktion aufruft, die überprüft welche Elemente angeklickt wurden.

Bei jedem angeklickten Bild (allPics.forEach((element, index)) wird in einer if-Verzweigung überprüft, ob eine der beiden (mit einem logischen oder verknüpften Bedingungen zutrifft:

  • evt.target == element - das Element innerhalb von allPicswurde geklickt
  • evt.target == element.parentNode - das Elternelement, also der umgebende Link wurde geklickt.
Falls die Bedingung zutrifft, wird index der Variable currentPic zugewiesen und die Großansicht aktiviert.
		[caption, figure, full, next, prev].forEach(element => {

			if (evt.target == element) {
				showFull = true;

				if (element == next && currentPic < allPics.length -1) {
					currentPic++;
				}

				if (element == prev && currentPic) { // kürzer als (currentPic > 0)
					currentPic--;
				}
			}
		});
Nun wird überprüft, ob der next- oder der prev-Button angeklickt wurde. In einer If-Abfrage wird überprüft, ob der next-Button angeklickt wurde und currentPic kleiner als allPics.length - 1 ist. Nur dann wird mit currentPic++ (entspricht currentPic = currentPic +1; der Zähler um 1 erhöht. Wenn der prev-Button angeklickt wurde und currentPic existiert, kann der Zähler um 1 verringert werden. Steht der Zähler auf 0, wird die Bedingung nicht erfüllt.
		
		if (showFull) {
			full.src = allPics[currentPic].parentNode.href;
			caption.textContent = allPics[currentPic].alt;
			figure.removeAttribute('hidden');

			if (currentPic < allPics.length -1) {
				next.removeAttribute('hidden');
			} else {
				next.setAttribute('hidden', 'hidden');
			}

			if (currentPic) {
				prev.removeAttribute('hidden');
			} else {
				prev.setAttribute('hidden', 'hidden');
			}
Wenn showfull wahr ist, weil ein Bild angeklickt wurde, wird die URL des a-Elements dem dynamisch erzeugten img-Element innerhalb des figure-Containers zugewiesen. Der alt-Text des thumbnails wird als caption unterhalb dargestellt. Die Vor- und Zurück-Buttons werden eingeblendet, indem mit removeAttribute das hidden-Attribut entfernt wird. Dies erfolgt aber nur, wenn eine solche Aktion auch möglich ist.
			evt.preventDefault();
		} else {
			// Großansicht unsichtbar schalten
			lightbox.close();
		}
	});

Am Ende findet sich das evt.PreventDefault, mit dem die Links ihrer Funktionalität „beraubt“ wurden und im abschließenden else findet sich der Fall, dass der „schließen“-Button geklickt wurde. Dann wird das figure-Container-Element und die in ihm erhaltenen img- und -figcaption-Elemente sowie die Buttons wieder ausgeblendet.

CSS: Der letzte Schliff

Es ist wichtig, dass Buttons durch ihren Textinhalt oder ein label für alle verständlich und ihre jeweiligen Bedienzustände (:hover und :focus) erkennbar sind.

Trotzdem ist ein X oft attraktiver als ein Schließen-Text, der evtl. noch in mehreren Sprachen verfügbar sein muss. Deshalb werden die Buttons nun grafisch so gestaltet, dass sie als Symbole klar erkennbar sind. Ihr Textinhalt bleibt für Screenreader jedoch erhalten:

dynamischer Bildwechsler - Endzustand ansehen …
#fullview button {
	position: absolute;
	top: 0;
	right: 0;
	width: 2rem;
	height: 2rem;
	cursor: pointer;	
	border: 0; 
	font: 0/0 a; 
	text-shadow: none; 
	background: transparent;
	color: transparent; 	
}

#fullview button:nth-of-type(1) {
background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100' height='100' fill='black' rx='10' /%3E%3Cpath d='M20,20 l60,60 m0,-60 l-60,60' fill='none' stroke='white' stroke-width='15' stroke-linecap='round'/%3E%3C/svg%3E");
background-size: contain;
}
#fullview button:nth-of-type(1):hover,
#fullview button:nth-of-type(1):focus {
background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100' height='100' fill='red' rx='10' /%3E%3Cpath d='M20,20 l60,60 m0,-60 l-60,60' fill='none' stroke='white' stroke-width='15' stroke-linecap='round'/%3E%3C/svg%3E");
}

Die Buttons werden nun mittels Image-Replacement ausgeblendet (transparente Text- und Hintergrundfarbe, Schriftgröße 0 und kein Rand).

Dann wird für jeden Button ein Hintergrundbild festgelegt, dass als Inline-SVG im CSS notiert wird. Wichtig ist hier, dass die Grafiken URL-encodiert werden müssen, so dass Zeichen wie # und < escaped werden.

Für :hover und :focus werden andere Farben (im stroke, bzw. fill-Attribut) festgelegt. Es wäre einfacher, dies gleich im CSS zu tun (#fullview button:nth-of-type(1) rect{fill: red;}- dann müsste das SVG aber Teil des HTML-Markups sein, was wiederum bei der dynamischen Erzeugung komplizierter wäre.

Fazit: Nach dem Prinzip der Trennung von Inhalt, Präsentation und Verhalten bleiben HTML-Markup und JavaScript unverändert. Nur das Aussehen wird durch CSS neu gestaltet, wobei die Zugänglichkeit immer gewährleistet bleibt.

Polaroid-Bildergalerie

Diesen Bildwechsler kann nun bei jeder Bildgalerie verwendet werden.

In dieser Bildergalerie werden Bilder als kleinere Vorschauansichten angezeigt. Ein Anwählen mit Maus, Touch oder Tastatur öffnet die Dialog-Box, die nun mit CSS wie ein Polaroid-Foto gestylt wird. Zusätzlich erscheint die bisher verborgene figcaption als Bildunterschrift.

Polaroid-Bildergalerie ansehen …
dialog::backdrop {
				box-sizing: border-box;
				background-color: silver;
				background-image: linear-gradient(335deg, #b00 23px, transparent 23px),
				linear-gradient(155deg, #d00 23px, transparent 23px),
				linear-gradient(335deg, #b00 23px, transparent 23px),
				linear-gradient(155deg, #d00 23px, transparent 23px);
				background-size: 58px 58px;
				background-position: 0px 2px, 4px 35px, 29px 31px, 34px 6px;
				padding: 30px 0 140px 0;
			 /* weitere Muster mit linear-gradient unter: http://lea.verou.me/css3patterns/   */
			   opacity:0.8;
}

#lightbox figcaption {
	color: #333;
	font-size: 200%;
	font-family: "Reenie Beanie", cursive;
	position:relative;
	text-align: center;
}


Fazit: Bei beiden Beispiel werden die Bilder abrupt ohne weichen Übergang gewechselt. Eine Animation des Übergangs können Sie mit unserem Komfort-Bildwechsler erreichen.


Siehe auch


Exkurs: Karussell mit CSS-animation

Ein Bilderkarussell ist eine Animation, mit der Sie Bilder in einem festen Rhythmus wechseln können. Während ein image-fader Bilder ein-, bzw. überblendet, schiebt ein image-slider die Bilder ein.[1][2]


Beachten Sie: Bevor Sie diese Technik auf Ihrer Webseite übernehmen, sollten Sie sich aber über die Nachteile eines Karussells im Klaren sein:
  • Inhalte sind nicht sofort ersichtlich und (mindestens) einen Klick oder Wischer vom Nutzer Ihrer Seite entfernt.
  • Viele Nutzer warten nicht den Durchlauf eines Karussells ab, sondern verlassen die Seite vorher.
  • Manchen geht eine solche Animation zu langsam und wollen weiter klicken - anderen geht es zu schnell oder leiden gar unter den schnellen Bewegungen, so wäre es empfehlenswert zu überprüfen, ob diese Nutzer die Benutzereinstellung prefers-reduced-motion gewählt haben. Dann könnte man die Animation abstellen oder nur auf Benutzerwunsch starten (siehe Fazit).

Früher wurde so etwas mit JavaScript oder jQuery realisiert; aber mit CSS3 schien eine Umsetzung mit CSS einfacher, performanter und eleganter.

Beachten Sie: Auch wenn viele Anfänger sich anfangs erst einmal auf HTML und CSS beschränken wollen, hat dieses CSS-Karussell einige schwerwiegende Nachteile:
  • Der Nutzer kann nicht vor- und zurückblättern
  • Die Animation verwendet Magic Numbers - feste Werte, die sich bei einer Änderung der Bildanzahl nur schwer ändern lassen!

HTML: Struktur

Für die HTML-Struktur legen wir 3 Bilder in ein div mit der class gallery. Die Bilder werden von einem figure-Element mit einer zusätzlichen figcaption für eine Bildunterschrift umschlossen.

Beispiel ansehen …
<div class="gallery">
  <figure>
    <img src="" alt="">
    <figcaption>morgens</figcaption>
  </figure>
  <figure>
    <img src="" alt="">
    <figcaption>mittags</figcaption>
  </figure>  ...
</div>

CSS: Ausrichtung und Position

Beispiel
.gallery {
  position: relative;
}

.gallery figure {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}

.gallery figcaption {
  position: absolute;
  left: 1em;
  bottom: 0.5em;
  z-index: 2;
}

Durch die absolute Ausrichtung der figure-Elemente werden sie übereinander gelegt. Da die figcaption einen z-index von 2 hat, wird sie über die Bilder gelegt und am unteren Rand ausgerichtet.

Beachten Sie: Da die Bilder übereinanderliegen, ist das dritte Bild nun das oberste. Falls die Reihenfolge der Animation wichtig ist, müssen Sie sie umstellen.

Animation

Für die Animation verwenden wir die zusammenfassende CSS3-Eigenschaft animation.

Beispiel
.gallery figure {
  animation: wechseln 15s infinite;
}

Es wird nun eine Animation mit dem Namen wechseln aufgerufen, die 15s dauert und durch den Wert infinite unendlich oft wiederholt wird.

Sie können auch die Einzeleigenschaften verwenden:


Beachten Sie: Sie benötigen für die Eigenschaft animation für ältere Versionen von Safari und Android noch den Browserpräfix -webkit-, der hier aus Gründen der Vereinfachung weggelassen wurde.

Anlegen der einzelnen Animationsschritte

Zu jeder Animation gehört eine Festlegung der einzelnen Animationsschritte mittels der @keyframes-Regel.

Beispiel
@keyframes wechseln {
    0% {opacity: 0;}
   20% {opacity: 1;}
   40% {opacity: 1;}
   60% {opacity: 0;}
  100% {opacity: 0;}
}
Die @keyframes-Regel wird durch den Namen wechseln aufgerufen.

Die Prozentangaben stellen die einzelnen Animationsschritte dar. In den geschweiften Klammern finden Sie nun die CSS-Eigenschaft opacity, die die Deckkraft (oder Transparenz) festlegt.

Wenn die Animation aufgerufen wird, animiert sie dann das figure-Element anhand der angegebenen Werte. Anfänglich ist das figure-Element bei opacity: 0; transparent. Es wird bis 20% der Animationsdauer komplett deckend und damit sichtbar.

Damit die Bilder nicht abrupt wechseln, können Sie durch die Festlegung von weichen Übergängen eine langsame Überblendung erreichen. So bewirkt der Bereich von 20%-40% ein langsames Transparentwerden des oberen Bildes und Aufdecken des darunter befindlichen Bildes.

Nachdem ein Set von keyframes komplett durchlaufen wurde, beginnt die Abfolge von vorn. Nach 15 Sekunden wird das Bild also langsam wieder sichtbar.

Um zu vermeiden, dass dabei der Hintergrund sichtbar wird, müssen die Prozentpunkte der Keyframes genau auf die Anzahl der Bilder abgestimmt sein. Dazu mehr im folgenden Abschnitt.

Taktung der Animation

In einigen Beispielen im Web bekommt jedes Bild seine eigene Animation. Einfacher ist es aber, die vorliegende Animation mehrfach aufzurufen und zeitversetzt zu starten. Der Zeitversatz hängt damit von der Anzahl der Bilder in der Animation ab. In unserem Beispiel verwenden wir drei Bilder, die alle 5 Sekunden wechseln sollen. Deswegen beträgt die Gesamtdauer der Animation 15 Sekunden, das zweiten Bildes wird um 5 Sekunden und das dritten Bild um 10 Sekunden verzögert.

Durch die Einteilung der Keyframes ergibt sich für die Sichtbarkeit der einzelnen Bilder das folgende Diagramm:

Taktung der Animation

So erklären sich auch die Prozentangaben für die Keyframes. Das zweite Bild beginnt die Animation, wenn das erste Bild bei 33% ist. Um einen fließenden Übergang zu erhalten, muss es eine Zeit geben, in der beide Bilder teiltransparent sind. Durch die volle Sichtbarkeit in der Zeit von 20% bis 40% ergibt sich eine Teiltransparenz in der Zeit von 40% bis 53% des ersten Bildes. Danach ist das zweite Bild voll sichtbar.

Beispiel ansehen …
.gallery figure:nth-of-type(2) {
  animation-delay: 5s;
}
.gallery figure:nth-of-type(3) {
  animation-delay: 10s;
}

Die Eigenschaft animation-delay erlaubt das verzögerte Starten einer Animation. Für das obere, im HTML-Code dritte Bild benötigen Sie keine Verzögerung, sehr wohl aber für die folgenden Bilder.

Sie werden mit der strukturellen Pseudoklasse first-of-type angesprochen und erhalten jetzt eine Verzögerung. Fünf Sekunden nachdem das erste Bild transparent wird, startet nun die Animation für das mittlere Bild und danach die für das untere, im HTML-Code erste Bild.


Umrechnen für andere Bilderanzahl

Die im Beispiel genannten Zahlen sind für drei Bilder ausgelegt. Will man eine andere Anzahl animieren, muss man die angegebenen Zeiten umrechnen. Dafür dient die folgende Herleitung (wenn Sie sie nicht verstehen, ist das nicht schlimm, unten steht das Ergebnis):

Wichtige Zeitpunkte im Animationsablauf
Zeitpunkt Bild 1 Bild 2
0% Fade-In beginnt
20% Fade-In endet
33% Fade-In beginnt
40% Fade-Out beginnt
53% Fade-In endet
60% Fade-Out endet
73% Fade-Out beginnt

Das zweite Bild wird ab d=33% oder 1/3 der gesamten Zyklusdauer eingeblendet (d wie delay). Im Vergleich dazu beginnt die volle Sichtbarkeit des ersten Bildes bei t1=20% (1/5) und endet bei t2=40% (2/5) der Zyklusdauer. Bei t2 beginnt der Fade-Out und endet bei t3=60% (3/5). Wir brauchen jetzt die Relation, in der t1, t2, t3 und d zueinander stehen. Das Verhältnis von t1 zu d beträgt 1/5 geteilt durch 1/3, ergibt 3/5. t1 muss also 3/5 von d betragen. Die Keyframes liegen im gleichen Abstand, die weiteren Zeitpunkte sind also das Doppelte und das Dreifache von t1.

Animiert man nun beispielsweise 10 Bilder, beträgt der Versatz zwischen den Bildern d=100/10=10% der Zykluslänge. 3/5 von 10% sind 6%, und damit ergibt sich als @keyframes-Definition

Die @keyframes-Regel für 10 Bilder
@keyframes wechseln {
    0% {opacity: 0;}
    6% {opacity: 1;}
   12% {opacity: 1;}
   18% {opacity: 0;}
  100% {opacity: 0;}
}
Taktung der Animation für 10 Bilder

Varianten mit Zoom

Im vorliegenden Beispiel werden die Bilder durch transform: scale(0,0); bis zur Unsichtbarkeit verkleinert und gleichzeitig ausgeblendet..

Beispiel ansehen …
@keyframes bilder {
    
   0% {opacity: 1;} 
  34% {opacity: 1;}
  35% {opacity: 0;}
 100% {opacity: 0;}
}

.gallery figure:nth-of-type(1) {  
  animation: bilder 15s 7s infinite;
}

.gallery figure:nth-of-type(2) {  
  animation: bilder 15s 2s infinite;
}

.gallery figure:nth-of-type(3) {  
  animation: bilder 15s 12s infinite;
}

@keyframes wechseln {
    0% {opacity: 1; transform: scale(1,1); z-index: 20;}
   20% {opacity: 1; transform: scale(1,1);}
   34% {opacity: 0; transform: scale(0,0);}
  100% {opacity: 1; transform: scale(0,0);}
}

.gallery figure:nth-of-type(4) { 
  animation: wechseln 15s 10s infinite;
}

.gallery figure:nth-of-type(5) {  
  animation: wechseln 15s 5s infinite;
}

.gallery figure:nth-of-type(6) {  
  animation: wechseln 15s infinite;
}
Beachten Sie: Die Bilder werden im HTML-Code doppelt angezeigt, damit nach dem Durchlaufen der Animation kein weißer Hintergrund zu sehen ist. So ist diese CSS-Animation eher ein proof of concept als eine best practice; trotzdem aber eine Alternative zu einer JavaScript-basierten Diashow.

Fazit

Wie bereits anfangs erwähnt, muss gesagt werden, dass es zwar möglich ist, Bilder mit CSS-animation in einem Fader ein- und auszublenden. Andererseits gibt es keine weiteren Steuerungsmöglichkeiten und viele Festlegungen der Animation befinden sich hartkodiert im CSS-Code, der bei Änderungen des Inhalts entsprechend angepasst werden müsste. Dazu kommt die Problematik, dass seitenfüllende Bilder angesichts der Vielzahl von möglichen Viewports nur schwer möglich sind.

Mit dem heute verpönten Checkbox-Hack können Sie eine Steuerung erreichen, wie in diesem Codepen-Beispiel von Marc Haunschild. Diese Funktionalität erhöht die Komplexität des CSS aber erneut um ein Vielfaches und ist nicht für alle Nutzer zugänglich!

Empfehlung: Bequemer und eleganter geht dies aber doch mit JavaScript, wie Sie in folgenden Tutorials sehen können.


Weblinks

  1. should i use a carousel?
  2. desandro.github.io: Carousel sehr gutes und anschauliches Tutorial zu 3d-transforms, das für die Interaktion aber JavaScript benötigt