von Andy Pillip
Responsive Image Maps
Mit CSS3 lässt sich eine flexible Image Map für das Responsive Web realisieren
In folgendem Vorschlag für Webentwickler werde ich auf einem Bild der Mitarbeiter von pressenter die Personen einzeln verlinken, wie in einer Image Map.
Der Code ist progressiv aufgebaut, ich denke also immer zuerst an kleine Bildschirme (mobile first), danach erst an Große.
Flexible Bilder (responsive Images)
Eine Basistechnik aus dem Responsive Design ist folgender einfacher CSS-Code:
img {width: auto; max-width: 100%; height: auto;}
Damit wird das Bild in der vorgegebenen Größe (width
und height
in HTML) dargestellt, so lange es in seinem Container (dem Elternelement) Platz hat.
Wird der Container kleiner als das Bild, wird dieses durch height: auto
verhältnistreu verkleinert. Auf Geräten mit kleinen Bildschirmen sind also bereits alle
Mitarbeiter zu sehen:
Optimierung für hochauflösende Bildschirme (z.B. Retina)
Bild in Höherer Auflösung abspeichern
Damit ohne viel Technik das Bild auch auf hochauflösenden kleinen Bildschirmen gut aussieht, habe ich das Bild in der zweifachen Größe angelegt, also in 320 px · 2 = 640 px.
Damit erscheint das Bild dann auch im Querformat (~480 px) noch relativ scharf bei hochauflösenden Geräten.
Auf Bildschirmen mit einer höheren physikalischen Auflösung als 640 px in der Breite wird es also unscharf.
Größeres Bild über CSS Mediaqueries nachladen
So lange die Techniken für Responsive Images noch in Entwicklung sind, mit denen der Browser das passend aufgelöste Bild selbst lädt, behelfe ich mir mit einem einfachen CSS-Trick, von dem mich zuletzt Simon überzeugt hat:
<figure id="imgmap">
<img src="mitarbeiter.jpg" width="640"
height="181" alt=""/>
</figure>
Das img-Element und die CSS-Regel von oben sorgen bereits dafür, dass der Container #imgmap um das Bild stets auch vertikal im Seitenverhältnis mitwächst. Mit der CSS-Anweisung
#imgmap img { width: 100%; }
sorge ich dafür, dass das Bild auch über seine tatsächliche Größe von 640 px hinaus vergrößert wird.
Weil ich in CSS mit Mediaqueries Kontrolle über die Auflösung des Gerätes habe, tausche ich dort das Bild aus. Vielmehr verstecke ich das Bild, und gebe dem Container, der die gleiche Größe hat, ein Hintergrundbild:
@media (min-width: 640px) {
#imgmap img { visibility: hidden; }
#imgmap {
background: url("mitarbeiter-1000px") no-repeat left
top;
background-size: 100% auto;
}
}
Mit der CSS3-Eigenschaft background-size
sorge ich dafür, dass auch das
Hintegrundbild stets mitwächst.
Links über das Bild legen
Jetzt fehlen noch die Links auf die Seiten der Mitarbeiter. Diese füge ich barrierefrei und semantisch korrekt in HTML ein:
<figure id="imgmap"><img src="mitarbeiter.jpg" width="640" height="181"
alt=""/>
<figcaption>
<a id="ma1" href="mitarbeiter1.html"
title="Mitarbeiter 1 kontaktieren">Mitarbeiter 1</a>
<a id="ma2"
href="mitarbeiter2.html" title="Mitarbeiter 2 kontaktieren">Mitarbeiter
2</a>
<a id="ma3" href="mitarbeiter3.html" title="Mitarbeiter 3
kontaktieren">Mitarbeiter 3</a>
<a id="ma4"
href="mitarbeiter4.html" title="Mitarbeiter 4 kontaktieren">Mitarbeiter
4</a>
<a id="ma5" href="mitarbeiter5.html" title="Mitarbeiter 5
kontaktieren">Mitarbeiter
5</a>
</figcaption>
</figure>
Das ähnelt eigentlich schon sehr stark dem Markup einer Imagemap.
Am Ende müssen diese Links über das Bild gelegt werden, was nur mit absoluter Positionierung über die IDs funktioniert. Die Links lassen sich natürlich nur rechteckig formen, und sollen das Bild in Spalten teilen.
#imgmap { position: relative; } /* für absolute Positionierung der Kindelemente
*/
a#ma1 { left: 0; width: 20%; }
a#ma2 { left: 20%; width: 20%; }
a#ma3 {
left: 40%; width: 20%; }
a#ma4 { left: 60%; width: 20%; }
a#ma5 { left: 80%;
width: 20%; }
Auf kleinen Bildschirmen macht es absolut keinen Sinn, dass die Mitarbeiter einzeln anklickbar sind, deshalb verstecke ich sie erst einmal, indem ich sie aus dem Container hinaus schiebe:
#imgmap { overflow: hidden; }
#imgmap a { position: absolute; top: 100%; height:
100%; }
Dadurch werden sie von Screenreadern immer noch vorgelesen, und bleiben mit der Tastatur ansteuerbar.
Wenn die Auflösung hoch genug ist, um einzelne Mitarbeiter mit dem Finger zu treffen, positioniere ich die Links an richtiger Stelle:
@media (min-width: 480px) {
#imgmap a { top: 0; }
}
Feinschliff
Mit weiteren Basisregeln, wie z.B. text-indent
, den Pseudoklassen :hover
,
:focus
und :active
sollte man die Links noch so gestalten,
dass der Text nicht mehr sichtbar ist und ein netter Effekt entsteht, wenn man einen
Mitarbeiter mit der Tastatur auswählt.
Für hochauflösende, große Bildschirme kann man auch noch einen Mediaquery und ein Bild mit 2000 px anlegen.
Wo diese Grenzen liegen, ob man schon bei kleineren Auflösungen größere Bilder lädt, bleibt jedem selbst überlassen. Man muss immer zwischen Ladezeiten und scharfem Bild abwägen.
Die versteckten Links sollten bei :focus
wieder an die Position über dem
Bild verschoben werden, um für Barrierefreiheit die Navigation mit der Tastatur zu
ermöglichen.
Plan B für ältere Browserversionen
Bei allen Techniken muss man natürlich auch an Browser denken, die die modernen Techniken nicht beherrschen.
Fehlende Mediaqueries
Wenn Mediaqueries nicht zur Verfügung stehen, werden die entsprechenden CSS-Regeln ignoriert. Das bedeutet in meinem Vorschlag, dass die Mitarbeiter einfach nicht verlinkt sind, und das 640 px große Bild geladen und vergrößert wird.
Natürlich kann man überlegen, auch auf den kleinsten Bildschirmen die Mitarbeiter schon zu verlinken, dann klappt das auch in älteren Browsern.
Fehlendes background-size
In meinem Vorschlag habe ich jetzt keinerlei Rücksicht auf Browser genommen, die die
CSS-Anweisung background-size
nicht beherrschen. In diesen wird der
Hintergrund also einfach links oben platziert und entsprechend abgeschnitten — wir
hatten auch ein Projekt, wo das optisch
funktioniert.
Man kann abwägen, ob es tatsächlich so viele Browser(versionen) gibt, die zwar Mediaqueries, aber kein background-size
beherrschen.
In dem hier genannten Projekt habe ich den modernizr benutzt, der die
Fähigkeiten des Browsers per JavaScript überprüft. Nur wenn der Browser background-size
beherrscht, wende ich die CSS-Regel zum Austauschen des Bildes an.
Dadurch dass ich in meiner Lösung ein echtes img
-Element verwende, lässt
sich die Image-Map auch komplett ohne ausgetauschtes Bild realisieren.
Alternativen
Eine Alternative wäre, das Bild der Mitarbeiter in einzelne Elemente zu zerstückeln, und mit Links zu versehen. Über CSS-Sprites wäre auch der Vorteil von nur einem Request gegeben.
Diese Lösung ist aber in der Wartung sehr aufwändig: der CSS-Code ist komplexer, und bei jeder Bildänderung müssen die Einzelbilder (in allen Auflösungen) überarbeitet werden.
Außerdem müssen die Sprite-Positionen für die Flexibilität in % angegeben werden, wenn sich also Mitarbeiter nahe stehen, kann es durch Rundungsfehler durch Überlappungen der Bilder kommen.