Thumbnails: CSS Overlay mit Vanilla Javascript

Eine typische Aufgabe in einer Gallery in einem Betrag oder Post: kleine Bilder als Thumbnail oder Vorschaubild beim Klick als Overlay mit einem animierten Spinner in voller Größe nachladen, anzeigen und beim nächsten Klick schließen.

Thumbnails beim Click in großer Version zeigen

Vom Thumbnail zum großen Bild

Für die große Darstellung eines Bildes gibt es Plugins und Libraries wie Sand am Meer, aber für eine begrenzte Nutzung muss nicht gleich der Overkill von jQuery bis Bootstrap eingesetzt werden.

Alle Bilder, die beim Klick vergrößert werden sollen, sitzen in einem einfachen a-Tag, das im href-Attribut die Adresse der großen Bildversion zeigt.

Das leere span class="spinner" ist der Spinner und bleibt verborgen, bis das Vorschaubild angeklickt wird.

Die großen Bilder in diesem Beispiel sind überdimensioniert, damit man den Spinner auch bei einer schnellen Internet-Verbindung zu Gesicht bekommt.

img2-s img3-s img4-s img1-s img5-s img6-s
<div class="flexpics">
   <a class="with-overlay" href="img1-l.jpg">
      <img class="thumbnail" src="img1-s.jpg" width="480" height="320" alt="img1-s">
   </a>
   <a class="with-overlay" href="img2-l.jpg">
      <img class="thumbnail" src="img2-s.jpg" width="400" height="267" alt="img2-s">
   </a>
</div>
…

Für kleine Monitore wäre der Overlay Overkill, denn dort werden Bilder vorzugsweise in der vollen Breite eingesetzt. Bei Handys, die im Landscape-Modus gehalten werden, wäre die Höhe des Bildes großer als die Höhe des Screens. Darum beginnt die Anzeige des Overlays erst ab einer bestimmten Größe des Viewports, z.B. bei 600px.

CSS für Vorschaubilder, Spinner und große Bildversion

@media only screen and (min-width:600px) {
	.flexpics {
		display: flex; 
		flex-wrap: wrap; 
		justify-content: space-between;
		position: relative;
	}
	a.with-overlay { 
		width: 30%;
		margin-bottom: 1ex;
	}

	.spinner { 
		width: 150px; 
		height: 150px; 
		position: absolute; 
		left: calc(50% - 75px); 
		top: calc(50% - 75px); 
		display: none;
	}
	
	.highRes { 
		position:absolute; 
		z-index:100; 
		left: 0; 
		opacity: 0; 
		animation: 
		fadeIn 0.5s forwards 
	}

	@keyframes fadeIn {
		from { opacity: 0}
		to { opacity: 1}
	}
}

spinner.svg ist eine mit CSS animierte Grafik.

Warten

Um den Spinner in der Mitte des Vorschaubilds zu platzieren und später die hochauflösende Version des Bildes ebenfalls vertikal mittig anzuzeigen, bekommt a.with-overlay die Eigenschaft display: flex. justify-content: center und align-items: center zentrieren die Elemente unterhalb von a.with-overlay horizontal und vertikal.

highRes ist die Klasse für die hochauflösende Bildversion. Das große Bild wird mit position absolute und left: 0 positioniert, so dass es immer am linken Rand des umfassenden Blocks liegt.

Javascript für den Overlay

Das Skript hängt den Spinner nachträglich unter den Block mit den Thumbnails.

const withOverlay = document.querySelectorAll(".with-overlay");
const spinner = document.createElement ("img");
spinner.src = "svg/spinner.svg";
spinner.classList.add ("spinner");
document.querySelector (".flexpics").append (spinner);

setTimeout (fct, time) simuliert während des Testens die Ladezeit. Nach den Tests nicht vergessen, den Timeout wieder zu entfernen.

Beim Klick verhindert evt.preventDefault() die default-Aktion des a-Elements – die Navigation zur Adresse des href-Attributs.

withOverlay.forEach ((elem) => {
	elem.addEventListener ("click", function (evt) {
		evt.preventDefault();
		const highRes = new Image();
		highRes.classList.add('highRes');
		document.querySelector (".spinner").style.display = "block";
		setTimeout (() => {
			// zuerst den Listener für das Laden des Bildes
			highRes.addEventListener ('load', function () {
				document.querySelector (".spinner").style.display = "none";
				document.querySelector (".flexpics").appendChild(highRes);
			});
			
			// src erst nach dem Aufsetzen des Listeners angeben
			highRes.src = this.href;
		}, 2000)
		
		highRes.onclick = function () {
			this.remove ();
		}
	});
});

Das Script muss im Fuß der Seite eingesetzt werden, am besten vor das schließende body-Element.

Overlay Fullscreen

Damit das hochauflösende Bild fullscreen angezeigt wird, muss nicht das Javascript, sondern das CSS geändert werden.

Eine Möglichkeit

@media only screen and (min-width:600px) {
  body { position:relative} // zusätzlich
  .flexpics { 
     display: flex; flex-wrap: wrap; justify-content: space-between; 
     position: relative; 
  }

  .highRes { 
     position:absolute; z-index:100; left: 0; 
     width: 100vw; 
  }
}

Overlay einblenden

Auch das weiche Einblenden des Overlays ist CSS-Sache.

.highRes { … opacity: 0; animation: fadeIn 1s forwards } // zusätzlich
@keyframes fadeIn {
    from { opacity: 0}
    to { opacity: 1}
}

Beispiel Download

Suchen auf mediaevent.de