SVG - Scalable Vector Graphics... skalieren?!

SVG und Skalierung

Sie tragen es schon im Namen: SVG, Scalable Vector Graphics, lassen sich skalieren. Noch besser: sie lassen sich skalieren, ohne an Qualität zu verlieren – sie verpixeln nicht. Soweit, so gut. Der Traum vom verlustfreien Skalieren hält allerdings nur solange, wie man das SVG bereits in der gewünschten Größe importiert. Kommt man jedoch auf die verwegene Idee, ein SVG in einen Container, beispielsweise ein Div, zu packen, und möchte man dann vielleicht auch noch, dass sich besagtes SVG an die Größe dieses Containers anpasst, gerät man leicht in Verzweiflung.

Die Zauberworte, oder vielmehr Zauberattribute, die alles wieder gut machen können, heißen viewBox und preserveAspectRatio.

 

Skalieren mit „normalen“ Bildern

Bei den üblichen Bilddateien, beispielsweise .jpg oder .png, kann man auf ganz einfache Art und Weise dafür sorgen, dass das Bild seine Größe ändert: Das img selbst bekommt die Anweisung width: 100%; der übergeordnete Container eine fixe Breite. Die Höhe wird automatisch angepasst. Fertig.




Die Klasse .img-box ist hier für den schwarzen Rahmen und, viel wichtiger, für die Breite des Containers verantwortlich:

 




Das Originalbild hat eine Größe von 300 x 294 Pixeln; es passt sich aber problemlos den veränderten Maßen des übergeordneten Containers an. Die Seitenverhältnisse werden automatisch dadurch beibehalten, dass entweder nur die Breite oder nur die Höhe angegeben wird; der andere Wert wird automatisch angepasst.

 

SVG an Containergröße anpassen

Versucht man dies mit einer Grafik mit der Dateiendung .svg, kann es sein, dass man aufgrund der Angaben, die dieses Bild schon mitbringt, zu einem ähnlich zufriedenstellenden Ergebnis gelangt. Anders jedoch, wenn man ein SVG direkt mittels HTML-Tag[1] einbinden möchte.








Mit den gleichen Angaben für das SVG wie oben für das IMG (einziger Unterschied: grüne Hintergrundfarbe) kommt man nämlich zu einem anderen Ergebnis:

 





Das SVG selbst hat einen grünen Hintergrund, darauf befindet sich ein orangefarbenes Rechteck und ein umrahmter gelber Kreis. Im HTML-Teil sieht das so aus:



 

Stimmt, das SVG hat eine Breite und Höhe angegeben. Behält man alle anderen Settings bei und lässt nur diese width und height weg, ist das Ergebnis allerdings noch unschöner:

 



Offensichtlich braucht man also für SVG eine andere Herangehensweise, um sie ihren übergeordneten Containern anpassen zu können.

 

Das ViewBox-Attribut

Dafür gibt es das Attribut viewBox. Dieses setzt sich wiederum aus vier Werten zusammen: min-x, min-y, width und height, die durch Kommata oder mittels Leerzeichen getrennt werden. Leider sind diese Werte nicht so intuitiv verständlich, wie man sich das wünschen würde. Beginnen wir mit letzteren beiden.

 

ViewBox: width und height

Die Werte für width und height im viewBox-Attribut stehen NICHT dafür, wie breit und hoch das Endergebnis sein soll, sondern werden zur Berechnung des Verhältnisses zur ursprünglichen Größe gebraucht. Um das etwas anschaulicher zu erklären, nehmen wir das SVG von weiter oben, allerdings diesmal mit dem orangefarbenen Rechteck kleiner und in der linken oberen Ecke.

 



Das Rechteck hat hier eine Breite von 20, das SVG selbst (mit grünem Hintergrund) eine Breite von 200, das SVG ist also zehnmal so breit wie das darin liegende Rechteck. Das Ergebnis sieht folgendermaßen aus:

 


 

Das SVG selbst hat der besseren Übersichtlichkeit wegen einen schwarzen Rahmen und eine grüne Hintergrundfarbe (in CSS definiert).

Und nun zum mysteriösen viewBox-Attribut. In diesem Fall sind width und height im viewBox-Attribut gleich der width und height des SVG. Das bedeutet, sie verhalten sich im Verhältnis 1:1. Oder anders ausgedrückt: SVG-width/viewBox-width = 1.

Möchte man nun skalieren, kann man sich diese width und height der viewBox zunutze machen: Soll das orangefarbene Quadrat doppelt so breit werden, setzt man die viewBox width auf die Hälfte. Klingt im ersten Moment vielleicht verwirrend, macht aber aufgrund des Verhältnisses Sinn: SVG-width/viewBox-width, in diesem Fall 200/100 = 2.



 

Ergebnis:




Soll sich das orangefarbene Quadrat über das ganze (grüne) SVG erstrecken, müsste es also 10x so breit sein. Die viewBox width und height müssten also auf 20 gesetzt werden, denn: 200/20 = 10 (svg-width/viewBox-width).


Ergebnis:

 



Wie hier jetzt gut zu sehen ist, betrifft diese Skalierung auch die anderen Größenangaben, die innerhalb des SVG gemacht wurden; auch der Rahmen des Kreises ist entsprechend breiter geworden.

Verpackt man nun dieses SVG in ein Div und gibt ihm eine fixe Breite, kommt zunächst die Enttäuschung: Das SVG hat sich nicht an die neue Größe angepasst. Dazu bleibt noch eins zu tun: width- und height-Angabe aus dem <svg>-Tag löschen. Dann kann über die Größenangabe des übergeordneten Divs skaliert werden.




Dieses einfache Beispiel ist hier auf codepen zu finden.

 

ViewBox: min-x, min-y

Fein, das mit der Größe funktioniert jetzt schon mal. Wozu sind aber die ersten beiden Werte da, die dem viewBox-Attribut zugeordnet werden?

Wer jetzt „Koordinatensystem“ gedacht hat, ist schon – teilweise – auf dem richtigen Weg. Sehen wir uns einmal an, was passiert, wenn wir diese beiden Werte in unserem Beispiel von eben auf 10 setzen.






Hübsch, aber vermutlich nicht das, was man eigentlich erwarten würde. Wir verschieben mit diesen beiden Koordinaten nicht den Inhalt um die angegebenen Werte, sondern definieren einen neuen Startpunkt innerhalb unseres SVG; dieser Startpunkt liegt dann in der linken oberen Ecke.

Soll der gesamte Bildausschnitt verschoben werden, kann man das über diese beiden Werte erreichen. Hier können (anders als bei width und height) auch negative Werte vergeben werden. Möchte man das Ergebnis erreichen, das man aufgrund der Erfahrung mit Koordinatensystemen im HTML/CSS-Bereich hat, muss man hier umdenken. Um das orangefarbene Rechteck nach unten und nach rechts zu verschieben, müssen in der viewBox negative Werte für min-x und min-y vergeben werden.

Wieder unlogisch? Nur im ersten Moment. Wir definieren dadurch einen neuen 0,0-Punkt für unseren Bildausschnitt. Wenn wir negative Werte verwenden, liegt dieser Startpunkt außerhalb der eigentlichen Grafik. Unser Rechteck wirkt also, als wäre es nach rechts unten verschoben worden. Tatsächlich liegt aber der absolute Nullpunkt unseres Koordinatensystems außerhalb der eigentlichen Grafik.


 


Ergebnis:

 

 

 

Auch einzelne Elemente innerhalb des SVG lassen sich positionieren: über die x- und y-Koordinate im jeweiligen Tag. Soll beispielsweise nur das orangefarbene Rechteck verschoben werden, wird der entsprechende Startpunkt für das Rechteck über die x- und y-Koordinate direkt im <rect>-Tag gesetzt.






 

Bitteschön: orangefarbenes Rechteck verschoben.

 

preserveAspectRatio

Es gibt noch ein weiteres hilfreiches Attribut, das uns erlaubt, SVG anzupassen: preserveAspectRatio. Diese Angabe greift bei SVG nur, wenn auch viewBox definiert ist; ohne viewBox-Angabe wird preserveAspectRatio ignoriert.

Das Default-Setting für preserveAspectRatio ist "xMidYMid meet" und muss nicht explizit gesetzt werden. Es bedeutet nichts anderes, als dass das Bildseitenverhältnis beibehalten werden soll.

Möchte man, dass sich das SVG dem übergeordneten Container ohne Rücksicht auf das Bildseitenverhältnis anpasst, bzw. über width und height Angabe verzerrt werden kann, kann man das mittels preserveAspectRatio="none"; erreichen.

 



Dazu braucht man allerdings auch wieder die Breiten- und Höhenangabe für das SVG; in diesem Fall (mit übergeordnetem Container, der eine Höhen- und Breitenangabe hat) width="100%" und height="100%".

Auch dieses einfache Beispiel ist auf codepen zu finden: Link zum Beispiel

 

Wer noch etwas in die Tiefe gehen möchte: Dem preserveAspectRatio-Attribut können zwei Parameter übergeben werden. Der erste ist der sogenannte align-Parameter. Er ist uns im Beispiel oben schon begegnet, als Default-Wert "xMidYMid" und als "none". Der zweite, optionale, Parameter ist der meetOrSlice-Parameter, ebenfalls schon kurz erwähnt im Default-Setting.

Für die meisten Anwendungsfälle werden das Default-Setting oder die Anweisung preserveAspectRatio="none"; völlig ausreichen. Eine vollständige Übersicht über alle möglichen align-Parameter gibt es in der Dokumentation.

 

Tipps & Hinweise 

*) Grafiken mit der Dateiendung .svg haben normalerweise schon ein viewBox-Attribut gesetzt.

 

Da wir hier mit XML zu tun haben, sind ein paar Kleinigkeiten zu beachten:

*) Alle Tags müssen geschlossen werden.

               Bsp.: <rect fill="blue" />

*) XML ist Case-Sensitive! Schreibweise von Attributen oder Parametern beachten!

               Bsp.: preserveAspectRatio="xMidYMid meet";

 

 

 



[1] SVG basiert auf XML. Es kann im HTML-Teil mittels <svg>-Tag eingebunden werden.

Kommentare sind geschlossen