SVG für responsive Webseiten

SVG responsive: Fit into Container auch in IE9, IE10 und IE11

SVG-Grafiken sind fast immer deutlich kleiner als Bitmaps und passen sich eigentlich ohne Verluste automatisch an das Platzangebot an.

Das »eigentlich« verrät schon die Crux: Die Größenanpassung funktioniert nicht ohne Weiteres in Internet Explorer. Responsives SVG braucht ein paar Kniffe, um sich widerstandslos an die Größe des Containers anzupassen.

Allen voran: viewBox

Das SVG-viewBox-Attribut bestimmt den sichtbaren Ausschnitt und das Seitenverhältnis. Nur nicht übersehen, dass viewBox mit einem großen »B« geschrieben wird! Und: Ältere Versionen von Inkscape haben das viewBox-Attribut nicht gesetzt.

              +–+–– Nullpunkt der Grafik 
              | |
<svg viewBox="0 0 345 207" width="100%" height="100%">
                  |   |            |             |
                  V   V            V             V 
          absolute    absolute    relative     relative
          Höhe        Höhe        Breite       Breite
            
</svg>

Wenn das viewBox-Attribut vorhanden ist und width und height auf 100% gesetzt werden, passen alle modernen Browser die Grafik an das Platzangebot des umfassenden Containers an. Ist ja auch eigentlich kein Problem: Der dritte und vierte Posten in der viewBox geben das Seitenverhältnis der Grafik an.

SVG an Größe des umfassenden Elements anpassen
<figure style="max-width: 480px;margin: 1em auto">
<svg width="100%" height="100%" viewBox="0 0 345 207">
</figure>

Alle modernen Browser außer … IE9, IE10 und IE11. Die alten Internet Explorer halten die Höhe der Grafik bei 150px fest und passen dann die Breite an. Erst Microsoft Edge skaliert SVG korrekt in das umfassende Element, wenn viewBox gesetzt ist und

  • entweder width="100%" und height="100%" im SVG-Tag steht
  • oder das CSS svg {width: 100%} vorlegt.

Bis der Support für IE11 endet (offiziell 2020), bleibt die Größe von SVG-Grafiken in responsiven Webseiten Fummelei.

SVG skalieren mit canvas

Der übliche Tipp für responsives SVG auch in IE11 und älteren Versionen von Internet Explorer ist der padding-bottom-Trick, mit dem die alten Internet Explorer ausreichend Platz in der Höhe bekommen.

Eine elegante Alternative ist ein leeres HTML canvas-Tag: Mit einem leeren HTML canvas-Element und etwas CSS funktioniert die Größenanpassung exakt bei allen Seitenverhältnissen.

Bei einem canvas-Element bleibt das Seitenverhältnis konstant, wenn nur eine Dimension angepasst wird.

Hexenkessel: SVG mit HTML responsive machen durch ein canvas-Tag
Ein leeres canvas-Element
<div class="svginside" style="max-width:480px">
  <canvas width="430" height="260"></canvas>
  <svg height="100%" width="100%" viewBox="0 0 430 260">
		…
  </svg>
</div>
CSS für responsive SVG
canvas {
  display: block;
  width: 100%;
  visibility: hidden;
}

.svginside {
  position:relative;
  margin-left:auto; margin-right: auto;
}

.svginside svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

Das CSS muss nur einmal in die CSS-Datei gesetzt werden, die Klasse svginside gilt für alle SVGs auf allen Seiten. Das SVG-Element muss absolut positioniert sein und auf top:0; left:0 gesetzt werden, weil das canvas-Element den Raum aufzieht. Das canvas-Element bekommt einfach dieselben Werte für width und height wie der dritte und vierte Wert des viewBox-Attributs des SVG-Tags (allerdings immer ganzzahlig!).

SVG mit padding-bottom anpassen

Wenn der umfassende Container die Höhe nicht explizit ausweist, setzt IE die Höhe der SVG-Grafik mit 150px fest und passt dann die Breite an. Immerhin kann IE das Seitenverhältnis korrekt berechnen.

Die meist propagierte Lösung setzt auf – nicht ganz unkompliziertes – CSS. Der umfassende Container wird ebenfalls relativ, das SVG-Element absolut im umfassenden Container positioniert.

Die SVG-Grafik sitzt in einem Container mit class="svgframe".

<style>
.svgframe { 
   width:100%; 
   position: relative;
   display:inline-block; 
   vertical-align: middle;
   padding-bottom: 50%;  // berechnet aus dem Seitenverhältnis height/width
   overflow:hidden;
}

.frame svg { position: absolute }
</style>

<div class="svgframe">
<svg viewBox="0 0 1489 724" 
    width="100%" height="100%" 
    preserveAspectRatio="xMinYMin meet">
…
</div>

Detaillierte Beschreibung der einzelnen Schritte Make SVG Responsive.

Das Gelbe vom Ei ist diese Technik nicht, denn für jede Grafik muss das Seitenverhältnis Höhe:Breite individuell berechnet und als padding in CSS angegeben werden.

SVG mit Javascript anpassen

Einige Zeilen Javascript reichen, um padding-bottom für alle Grafiken der Seite anzupassen.

preserveAspectRatio ist nicht nötig. Das Wesentliche ist und bleibt das viewBox-Attribut.

<div class="svgframe">
   <svg width="100%" height="100%" viewBox="0 0 1353 442">
      <rect fill="gold" x="0" y="0" width="400" height="100" />
      …
   </svg>
</div>

<script>
var svg = document.querySelectorAll('.svgframe svg');
var len = svg.length; 
for (var i=0; i<len; i++) {
   if (svg[i].getAttribute('width') == '100%' && parseInt(svg[i].parentNode.clientWidth) > 0) {
      var viewBox = svg[i].getAttribute('viewBox');
      viewBox = viewBox.replace(/\s\s+/g, ' ');
      var w = viewBox.split(' ')[2];
      var h = viewBox.split(' ')[3];
      var x = h / w * 100;
      svg[i].parentNode.setAttribute('style', 'padding-bottom:' + x +'%');
   }
}
</script>

SVG in einem img-Tag

Das ist die einfachste aller Varianten: Die URL der Grafik sitzt im src-Attribut wie bei einem Bitmap-Bild und das Bild passt sich automatisch an die Größe des umfassenden Containers an.

Das funktioniert sogar in Internet Explorer: IE9, IE10, IE11 und Edge.

<style>
img { width: 100%}
</style>
   
<figure class="svgimg">
   <img src="accordion.svg" width="480" height="288" alt="SVG in einem image Tag">
</figure>

Wenn die SVG-Grafik mit einem HTML img-Tag eingesetzt wird, reicht es, img { width: 100% } im CSS zu notieren.

Die neueren Version von Adobe Illustrator und Inkscape setzen das viewBox-Attribut automatisch, aber ältere Versionen von Inkscape nicht.

Das gilt sowohl für inline-SVG als auch für SVG in einem img-Tag. Bei einem img-Tag muss nur im CSS img { width: 100%; height: auto } notiert sein – .

SVG in einem image Tag
In einem img-Tag funktioniert die Anpassung in allen Browsern – vorausgesetzt, das viewBox-Attribut ist in der SVG-Datei gesetzt.
Immer das viewBox-Attribut in das SVG-Tag der Grafik setzen und width- und height-Attribut der Grafik auf 100% setzen – das haben wir für ein responsives Webdesign sowieso bereits in der Hinterhand.

Ausschnitt mit viewBox festlegen

Das viewBox-Argument des SVG-Tags bestimmt den sichtbaren Ausschnitt einer Grafik mit nur vier Werten: x (Nullpunkt), y (Nullpunkt), width und height. x und y sind der Ursprung oder Nullpunkt des Koordinatensystems. Einen Bildausschnitt legt man durch einen neuen Nullpunkt und die Größe des Ausschnitts fest.

Auf kleinen Monitore macht es Sinn, nur einen Ausschnitt des Bildes / des Grafik zu zeigen. Das funktioniert mit Javascript und matchMedia.

SVG Ausschnitt über viewBox festlegen
var postman = document.querySelector ('#postman');
var mql = window.matchMedia("(min-width:740px)");

clipImage(mql); // Initialen Ausschnitt beim Laden der Seite festlegen

mql.addListener(clipImage); // Spezieller Event Listener für MediaQueryList

function clipImage(mql) {
    if (mql.matches) {
        postman.setAttribute('viewBox','0 0 1436 731');
    } else {
        postman.setAttribute('viewBox','180 120 600 600');
    }
}

Javascript matchMedia wird von Safari, Chrome, Opera und Firefox unterstützt, IE ab Version IE10.

Damit IE das Bild beschneidet, muss svg:not(:root) { overflow: hidden } im CSS notiert werden (das ist aber in allen normalize / boilerplate-Variationen schon vertreten).

SVG responsive: Fit into Container