Bilder im Internet/Bilder präsentieren
- 30min
- einfach
- Kenntnisse in
● Bilder in HTML einbinden
● Tooltips mit Popover
Meist werden Bilder nicht nur einzeln, sondern zusammen mit anderen Fotos in einer Bildergalerie präsentiert. In diesem Kapitel lernen Sie, wie Sie Bildergalerien mit HTML und CSS gestalten können.
Inhaltsverzeichnis
Zoom bei img:hover?
Ich möchte gerne, dass Bilder durch Überfahren der Maus in Großdarstellung angezeigt werden.
Diese Aufgabenstellung vernachlässigt zwei Aspekte bei Bildergalerien:
- Auf mobilen Geräten ist der Viewport so klein, dass auf eine Vorschauansicht verzichtet werden kann.
- Ein Bild sollte sowohl auf mobilen Touchgeräten ohne Tastatur als auch mit der Tastatur, z.B mit der Tab-Taste ( ↹ ), ausgewählt werden können.
Während solche Großansichten früher nur mit JavaScript oder jQuery verwirklicht wurden, kamen mit CSS3 und CSS-animation scheinbar einfache CSS-Lösungen auf. Diese stießen aber immer wieder auf Probleme:
- Bilder können mit :hover auf Mausberührungen reagieren, aber nicht auf ein „Durchtabben“ mit der Tastatur.
- Bilder, die durch :hover oder Klick in einer Großansicht dargestellt werden, ragen teilweise aus dem Viewport hinaus und sind so nicht sichtbar. Bei heute verpönten, pixelgenauen Layouts mag man mit absoluter Positionierung eine Feinjustierung vornehmen können, auf Mobilgeräten wird dies schnell zur Fummelei.
Mit JavaScript und der Intersection Observer API könnte man überprüfen, ob sich ein HTML-Element im Viewport befindet und wenn nicht - es entsprechend verschieben.)
Bilderzoom mit Grid Layout
Dieses Beispiel von Temani Afif[1] ordnet 9 Bilder in einem 3x3-Grid an. Mit :hover oder beim Durchtabben wird das aktive Bild gezoomt und die Bildunterschrift wird sichtbar:
.gallery {
--size: 10em; /* control the size */
--gap: 1em; /* control the gap */
--zoom: 2; /* control the scale factor */
display: grid;
gap: var(--gap);
grid-template-columns: repeat(3,auto);
width: calc(3*var(--size) + 2*var(--gap));
aspect-ratio: 1;
}
Das Element mit der Klasse gallery
erhält mit grid-template-columns drei Spalten ohne Breitenangabe. Diese wird über die width festgelegt, deren Wert mit der calc()-Funktion aus den custom properties für --size
und --gap
berechnet wird. Mittels der aspect-ratio-Eigenschaft wird diese Breite auch für die Höhe der Galerie übernommen.
Das gezoomte Bild ist nie breiter als die Galerie und bleibt somit immer im Viewport!
.gallery figure {
margin: 0;
padding: 0;
position: relative;
}
.gallery > figure img {
width: 0;
height: 0;
min-height: 100%;
min-width: 100%;
object-fit: cover;
cursor: pointer;
filter: grayscale(80%);
transition: .35s linear;
}
.gallery > figure:hover img,
.gallery > figure:focus img{
filter: grayscale(0);
width: calc(var(--size)*var(--zoom));
height: calc(var(--size)*var(--zoom));
}
.gallery figcaption {
position: absolute;
bottom: 0;
left: 0;
text-align: center;
width: 100%;
opacity: 0;
color: white;
background: rgb(0 0 0 / 0.3);
}
.gallery figure:hover figcaption,
.gallery figure:focus figcaption {
opacity: 1;
}
Im Originalzustand füllen alle Bilder ihr jeweiliges figure-Element aus. Mit der CSS filter-Eigenschaft wird ein Grauschleier grayscale(.8)
über die Bilder gelegt. Die Figcaption erhält einen dunklen Hintergrund und weiße Schrift, bleibt durch opacity: 0 aber unsichtbar.
Bei :hover oder dem Antabben wird nun das Bild mit grayscale(0)
wieder farbig; die Breite und Höhe werden über den --zoom
-Wert vergrößert. Die Änderung der Eigenschaftswerte erfolgt mit transition als weicher Übergang mit einer Dauer von 0.35s.
Auch die Figcaption wird nun eingeblendet.
Bildunterschriften
Um Bildern eine passende Erklärung oder Bildunterschrift zu geben ist das figcaption-Element in Verbindung mit dem figure-Container ideal. Es ist vor allem aus Gründen der Semantik den leider immer noch häufig anzutreffenden Lösungen mit verschachtelten div-Elementen vorzuziehen.
<figure>
<img src="lauf-1.jpg" alt="Lauf an der Pegnitz - Nürnberger Tor">
<figcaption>Lauf an der Pegnitz - Nürnberger Tor</figcaption>
</figure>
Als Container für das img-Element und die figcaption dient ein figure-Element.
Nur mit dem default-CSS der Browser sieht das Ergebnis zunächst einmal wenig ansprechend aus. Deshalb setzen wir unsere Vorstellungen mit ein wenig CSS um:
figure {
position: relative;
margin: 0;
padding: .5em;
width: 100%;
border: thin solid gainsboro;
background: white;
width: 100%;
}
@media (min-width: 25em) {
figure {
width: 20em;
float: right;
}
}
figcaption {
padding: .8em;
text-align: center;
}
Hier werden einige Einstellungen festgelegt, die erst später wichtig werden:
- Außen- (margin) bzw. Innenabstände (padding) festlegen,
- die Bildunterschrift mit text-align zentrieren,
Mehrere Bilder nebeneinander
Während in Fließtexten oft ein einzelnes Bild integriert ist, will man häufig mehrere Bilder nebeneinander präsentieren. Das figure
-Element kann auch verschachtelt werden:
<figure id="gallery">
<figcaption>Ansichten von Lauf an der Pegnitz</figcaption>
<figure>
<img src="//wiki.selfhtml.org/images/a/a6/Lauf-1.jpg" alt="Lauf an der Pegnitz - Nürnberger Tor">
<figcaption>Nürnberger Tor</figcaption>
</figure>
<figure>
<img src="//wiki.selfhtml.org/images/4/4a/Lauf-2.jpg" alt="Lauf an der Pegnitz - Pegnitz">
<figcaption>Brücke über die Pegnitz</figcaption>
</figure>
<figure>
<img src="//wiki.selfhtml.org/images/2/24/Lauf-3.jpg" alt="Lauf an der Pegnitz - Nürnberger Tor">
<figcaption>Mauermühle und Judenturm</figcaption>
</figure></figure>
Um die einzelnen Bilder nebeneinander zu positionieren, gibt es mehrere Möglichkeiten in CSS:
- Die figure-Elemente sind Block-Elemente, die mit
display: inline-block;
nebeneinander positioniert werden können
→ dafür müssen sie dann passende Breiten und Abstände erhalten. - ein ähnlicher Effekt ist mit flexbox möglich. Hier kann man mit justify-content noch bestimmen, wie ein einzelnes Kindelement in der letzten Zeile positioniert wird.
- mit Grid Layout wird das Elternelement zum Grid Container. Es kann eine feste Spaltenanzahl festgelegt werden, es ist aber auch möglich Raster implizit zu erzeugen, die durch den auto-placement-Algorithmus Rasterelemente automatisch auf den verfügbaren Platz verteilen.
#gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15em, 1fr));
gap: 1em;
}
#gallery > figcaption {
grid-column: 1 / -1;
}
Um im CSS ein figure figure
zu vermeiden, geben wir der Bildergalerie eine ID mit Namen gallery
.
Folgende Einstellungen sind wichtig:
-
display: grid
: erzeugt das Raster -
grid-template-columns: repeat(auto-fill, minmax(15em, 1fr));
: erzeugt Rasterlemente, die zwischen 15em und einem Bruchteil des verfügbaren Platzes breit sind. -
gap: 1em;
: erzeugt einen Abstand zwischen den Rasterelementen, aber nicht außen.
Einziges Problem ist die figcaption der gesamten Galerie. Ohne weitere Festlegungen würde sie das erste Rasterlement links neben dem ersten Bild einnehmen. Mit …
-
grid-column: 1 / -1;
erstreckt es sich aber über die gesamte Breite von der ersten bis zur letzten (-1 = von rechts gezählt) Rasterlinie
Einschwebende Bildunterschriften
Normalerweise ist figcaption
unterhalb des img
im figure
-Elternelement positioniert. Wir wollen es jetzt über den unteren Bildrand positionieren. Damit das Bild noch erkennbar bleibt, soll die Bildunterschrift einen durchscheinenden Hintergrund bekommen:
#gallery figure {
position: relative;
}
figure img {
width: 100%;
display: block;
}
#gallery > figure > figcaption {
position: absolute;
bottom: 0;
width: 100%;
line-height: 3em;
color: white;
background: rgb(0 0 0 / .3);
}
Zuerst müssen wir
a #gallery figure
relativ und
b #gallery > figure > figcaption
absolut positionieren.
Danach wird figcaption mit bottom: 0;
unten platziert.
bottom: 0;
auch wirklich mit dem figure, bzw. img-Element unten bündig abschließt, muss ebenfalls img {display: block;}
festgelegt werden.Folgende Einstellungen sind noch wichtig:
-
width: 100%;
: sorgt dafür, dass die Bildunterschrift über die gesamte Breite geht. -
color: white;
: der Text wird weiß, -
background: black;
: der Hintergrund ist als schwarzer, bzw. grauer Balken sichtbar. -
opacity: 0.3;
: Der Hintergrund wird durchscheinend. Dies gilt aber auch für den Text, sodass ein zu niedriger Wert < 0.3 fast nicht lesbar ist.
Der Hover-Effekt
Trotz durchscheinendem Hintergrund liegt nun ein Balken über unserem Bild. Wir können diesen im Normalfall verschwinden lassen und erst bei :hover bzw. :focus einschweben lassen:
#gallery > figure > figcaption {
opacity: 0;
bottom: -3em;
transition: all 1s ease;
}
#gallery > figure:focus > figcaption,
#gallery > figure:hover > figcaption {
opacity: 1;
bottom: 0;
}
Im mittleren Bild wird die Bildunterschrift im Normalzustand durch bottom: -3em;
unterhalb des Rands positioniert. opacity: 0
verhindert, dass die Bildunterschrift sichtbar ist.
Erst bei :hover
bzw. :focus
wird die Bildunterschrift mit opacity: 1;
sichtbar und durch bottom: 0;
an den unteren Rand geschoben.
Das overflow: hidden;
des figure-Element verhindert, dass die Bildunterschrift schon außerhalb des Bildes zu sehen ist.
#gallery > figure.mitte > figcaption {
width: 0;
left: 50%;
}
#gallery > figure.rechts > figcaption {
width: 0;
bottom: 50%;
left: 50%;
overflow: hidden;
}
Die mittlere Bildunterschrift hat zusätzlich eine Breite von 0
. Bei :hover
oder :focus
dehnt sich die Bildunterschrift aus der Mitte heraus in ihre Originalposition.
Die rechte Bildunterschrift entspringt in der Mitte des Bildes und schiebt sich dann nach unten.
Im html haben die figure-Elemente das Attribut tabindex=0
erhalten, damit sie für Tastaturbenutzer fokussierbar werden.
Wo kommt das Fragezeichen her?
Damit man überhaupt weiß, dass es eine (im Normalfall ja nicht sichtbare) Bildunterschrift gibt, wird mittels Pseudoelement ::before ein Fragezeichen im linken unteren Bildrand platziert.
#gallery figure::before {
content: "?";
position: absolute;
bottom: 1em;
left: 1em;
background: white;
color: black;
opacity: .7;
width: 1.5em;
height: 1.5em;
border-radius: 1em;
text-align: center;
font-size: 1.5em;
line-height: 1.5em;
transition: all 1s ease;
}
#gallery figure:focus:before,
#gallery figure:hover:before {
opacity: 0;
}
Sobald der Benutzer mit der Maus über das Bild fährt oder das Bild focussiert, verschwindet es wieder. Damit dieser Wechsel nicht zu abrupt erscheint, legen wir mit transition weiche Übergänge fest.
Siehe auch
- verzögert einschwebende Bildunter- und überschriften
In diesem Beispiel erhalten Bilder aus Alaska Titel und Bildunterschrift mit individueller Verzögerung.
Popover
Die open-ui.org hat es sich zur Aufgabe gemacht, für solche UI-Elemente optimierte Modelle zu entwerfen und diese zur Standardisierung einzureichen.[2]
Mit der neuen Popover API[3][4] können Sie schnell und einfach Popups und Lightboxen erstellen, die diese Funktionalitäten bereits browserseitig mitbringen. Es ist kein kompliziertes CSS oder gar JavaScript nötig!
<ul id="galerie">
<li><button popovertarget="image1"><img src="dummy-1.jpg" alt="Spaß in der Sonne"></button></li>
<li><button popovertarget="image2"><img src="dummy-2.jpg" alt="Berg im Morgennebel"></button></li>
<li><button popovertarget="image3"><img src="dummy-3.jpg" alt="Spaß in der Sonne"></button></li>
<li><button popovertarget="image4"><img src="dummy-4.jpg" alt="Korallenriff"></button></li>
<li><button popovertarget="image5"><img src="dummy-5.jpg" alt="Morgensonne am Gardasee"></button></li>
<li><button popovertarget="image6"><img src="dummy-6.jpg" alt="Via Appia, Rom"></button></li>
</ul>
<figure id="image1" popover>
<img src="dummy-1.jpg" alt="Spaß in der Sonne">
<figcaption>Spaß in der Sonne</figcaption>
</figure>
<figure id="image2" popover> <img src="//wiki.selfhtml.org/images/e/e7/Dummy-2.jpg" alt="Berg im Morgennebel">
<figcaption>Berg im Morgennebel</figcaption>
</figure>
……
Die Galerie besteht aus einer unsortierten Liste. So sind die Bilder als zusammengehörende Teilelemente erkennbar.
Die Thumbnails befinden sich innerhalb von Button-Elementen, die über das popovertarget-Attribut mit der id des Popovers verbunden sind. Als Buttons sind sie mit ihrem Standardverhalten sowohl mit Maus, als auch per Touch und Tastatur anwählbar.
Das Popover besteht aus einem figure-Element mit einem popover-Attribut. In diesem Container befinden sich das Bid mit alt-Attribut und einer Bildunterschrift in einer figcaption.
Die browsereigene Darstellung der Buttons ähnelt dem Rahmen eines Dias, sodass der Effekt einer Bildergalerie passend dargestellt wird. Jetzt muss nur das Popover formatiert werden:
[popover] {
background: lightyellow;
border: thin solid yelow;
max-width: 20em;
padding: 1rem;
margin: 2rem auto;
}
img {
padding: 0;
margin: 0;
width: 100%; /* Bild passt sich an verfügbaren Raum an */
}
figcaption {
text-align: center;
}
Die figure-Elemente enthalten alle das boolesche popover-Attribut. Über den Attributselektor [popover]
erhalten diese Elemente nun folgende Formatierung:
- einen hellgelben Hintergund und einen gelben Rand
-
max-width: 20em;
: eine maximale Breite von 20em; damit 4k-Bilder nicht den Viewport sprengen.
<script
src="https://cdn.jsdelivr.net/npm/@oddbird/popover-polyfill@latest"
crossorigin="anonymous"
defer
></script>
Fazit: Na ja!
Dieses Beispiel hat Stärken und Schwächen:
+ immer oberhalb des Inhalts
+ immer im Viewport
+ nur HTML, kein JavaScript nötig
– Niemand klickt ein Bild groß, dann klein und dann das nächste wieder groß - Warum gibt es keinen weiter-Button?
– HTML wird schnell zu umfangreich, warum sollte das nicht durch JavaScript benutzerfreundlicher angelegt werden?
Deshalb zeigen wir im nächsten Kapitel, wie Sie eine komfortable Lightbox mit Bildwechsler bauen können.
Siehe auch
Temani Afif zeigt auf css-tricks, wie man interessante Formen mit Grid Layout zu geometrischen Mustern anordnet:
CSS Grid and Custom Shapes, Part 1 von Temani Afif, 15.08.2022
Eric Meyer zeigt, wie man mit clip-path Bilder anschrägt und nebeneinander positionieren kann:
Flexible Captioned Slanted Images von Eric Meyer (24ways.org)
Weblinks
- ↑ Zooming Images in a Grid Layout von Temani Afif, 8. Aug 2022
- ↑ open-ui.org: Popover API (Explainer)
- ↑ WHATWG: 6.12 The popover attribute
- ↑ MDN: Popover API
- ↑ Popover Attribute Polyfill (github.com)