Das Folgende ist ein Gastbeitrag von Amelia Bellamy-Royds. Amelia hat viel Erfahrung mit SVG, als Co-Autorin von SVG Essentials und Autorin des kommenden Using SVG with CSS3 and HTML5. Amelia und ich werden beide auf dem kommenden RWD Summit über SVG sprechen! Hier teilt sie einen epischen Leitfaden zum Skalieren von SVG, der alle gewünschten Wege abdeckt. Es ist nicht annähernd so einfach wie das Skalieren von Rastergrafiken, aber das kann gut sein, da es interessante Möglichkeiten eröffnet.
Du hast die Entscheidung getroffen. Du wirst es endlich tun. Dieses Jahr wirst du anfangen, SVG in deinen Webdesigns zu verwenden. Du erstellst ein fabelhaftes Header-Logo in Inkscape und kopierst den SVG-Code, den es ausgibt, in deine WordPress-Header-Datei. Natürlich gibst du deine Auflösung vom letzten Jahr, immer Responsive Design zu nutzen, nicht auf, also setzt du svg.banner { width: 100%; height: auto; } in deinem CSS und denkst, du bist fertig.
Bis du deine Webseite in Testbrowsern öffnest und feststellst, dass einige riesige Blöcke von Weißraum oberhalb und unterhalb des Bildes hinterlassen, während andere es zu kurz beschneiden.
SVG steht für Scalable Vector Graphics. Das Skalieren von SVG sollte also einfach sein, oder? Das haben die SVG-Befürworter doch die ganze Zeit gesagt, dass SVG in jeder Größe gut aussieht? Das ist es, aber doch auch nicht. SVG sieht in jeder Größe großartig aus, aber es kann auf so viele verschiedene Arten skaliert werden, dass es für SVG-Anfänger verwirrend sein kann, es genau so verhalten zu lassen, wie du es möchtest. Es hilft auch nicht, dass Browser erst seit kurzem einen Standardansatz für die Größenanpassung von Inline-SVG-Inhalten übernommen haben.
SVG ist nicht (nur) ein Bild
Ein Grund dafür, dass das Skalieren von SVG so schwierig ist, liegt darin, dass wir eine bestimmte Vorstellung davon haben, wie Bilder skalieren sollten, und SVG verhält sich nicht auf die gleiche Weise.
Rasterbilder wie JPG, PNG und GIF haben eine klar definierte Größe. Die Bilddatei beschreibt, wie der Browser ein Raster einfärben soll, das eine bestimmte Anzahl von Pixeln breit und eine bestimmte Anzahl von Pixeln hoch ist. Eine wichtige Nebenwirkung ist, dass Rasterbilder ein klar definiertes Seitenverhältnis haben: das Verhältnis von Breite zu Höhe.
Man kann den Browser zwingen, ein Rasterbild in einer anderen Größe als seiner intrinsischen Höhe und Breite zu zeichnen, aber wenn man es zu einem anderen Seitenverhältnis zwingt, werden die Dinge verzerrt. Aus diesem Grund gibt es seit den frühen Tagen des Webs die Unterstützung für die auto-Skalierung bei Bildern: Man setzt die Höhe oder die Breite, und der Browser passt die andere Dimension an, damit das Seitenverhältnis konstant bleibt.
Das Skalieren von Rasterbildern gilt auch, wenn sie als background-image verwendet werden, nur dass wir die object-fit-Eigenschaft zur Größenanpassung und zum Beschneiden verwenden.
SVG-Bilder hingegen können in jeder Pixelgröße gezeichnet werden, daher benötigen sie keine klar definierte Höhe oder Breite. Und sie haben nicht immer ein klar definiertes Seitenverhältnis. Du musst diese Informationen (und mehr) explizit angeben, wenn das SVG so skaliert werden soll, dass es sich an die von dir vorgegebenen Dimensionen anpasst.
Wenn du das nicht tust, skaliert SVG überhaupt nicht. Das folgende Beispiel verwendet Inline-SVG und passt die Dimensionen des Elements (gestrichelte Linie) an, ohne die Größe der gezeichneten Grafik zu verändern
Warum verhält es sich so? Weil SVG nicht (nur) ein Bild ist. SVG ist ein Dokument. Obwohl das obige Beispiel Inline-SVG verwendet, könnte es genauso gut <object> oder <iframe> verwendet haben. Es würde genauso aussehen, selbst wenn du <img>-Tags verwenden würdest, um denselben SVG-Code einzubetten.
Wenn du eine HTML-Datei mit einem <iframe> inkludierst, erwartest du nicht, dass sich der Text darin skaliert, wenn du die Größe des Rahmens änderst. Dasselbe gilt für SVG. Standardmäßig wird es in der im Code angegebenen Größe gezeichnet, unabhängig von der Größe der Zeichenfläche. Was passiert, wenn du die Höhe oder Breite (oder beides) auf auto für diese SVGs setzt? Es wird die Standardgröße für ersetzte HTML-Elemente verwendet: 300px breit, 150px hoch. Das gilt für <img>, <object> oder <iframe>. Die Standardgröße von 300×150 gilt auch für Inline-<svg>-Elemente innerhalb von HTML-Dokumenten, aber das ist ein relativ neuer Konsens aus den HTML5-Spezifikationen: Andere Browser skalieren Inline-SVG standardmäßig auf die volle Größe des Viewports — äquivalent zu width: 100vw; height: 100vh; — was die Standardgröße für SVG-Dateien ist, die direkt in ihrem eigenen Browser-Tab geöffnet werden. Internet Explorer halbiert die Differenz und verwendet eine Breite von 100 % und eine Höhe von 150 px für Bilder und Inline-SVG.
Mit anderen Worten, selbst wenn du denkst, 300×150 sei eine perfekte Bildgröße (obwohl warum solltest du das tun?), verlasse dich nicht auf eine Standardgröße für <svg> in HTML.
Zusätzlich zur Entscheidung, welche Größe dein SVG haben soll, musst du dich auch entscheiden, wie dein Grafik sich an diese Größe anpassen soll. Unten beschreibe ich den Code, den du benötigst, um die Skalierung zu erreichen, die du für die häufigsten Situationen wünschst
- Skalieren, um sich an eine bestimmte Größe anzupassen, ohne das Bild zu verzerren
- Skalieren, um sich an eine bestimmte Größe anzupassen, wobei die Grafik nach Bedarf gedehnt oder gestaucht wird
- Skalieren, um sich an die verfügbare Breite anzupassen, während das Seitenverhältnis von Breite zu Höhe beibehalten wird
- Nicht-uniformes Skalieren, so dass sich einige Teile der Grafik anders skalieren als andere
Aber zuerst: Wenn du die Skalierung deines SVG kontrollieren möchtest, musst du dich mit den SVG-Skalierungsattributen und anderen verfügbaren Werkzeugen vertraut machen.
Die SVG-Skalierungs-Werkzeugkiste
Andere Bilder skalieren, weil der Browser die Höhe, Breite und das Seitenverhältnis des Bildes kennt und alles zusammen anpasst. SVG diese Eigenschaften zu geben, ist der erste Schritt, um es zum Skalieren zu bringen. Das Skalieren von SVG geht jedoch über das hinaus, was mit anderen Bildern möglich ist.
Die Attribute height und width
Ein erster Blick auf die SVG-Spezifikationen würde vermuten lassen, dass die Attribute height und width auf dem obersten svg-Element implizit ein Seitenverhältnis festlegen und SVG daher wie andere Bilder skalieren lassen. Es stimmt, dass das Setzen von Höhe und Breite die Standarddimensionen überschreibt, wenn man SVG als Bild verwendet. Aber natürlich ist es nicht so einfach.
- Wenn du ein
<img>verwendest, um dein SVG einzubetten, bewirkt das Setzen vonheightundwidth, dass sich das SVG in den meisten Browsern vorhersagbar skaliert, aber nicht in Internet Explorer. Mit CSS wieimg { width: 100%; height: auto; }skaliert IE den Bildbereich automatisch, um das Breiten-Höhen-Seitenverhältnis konstant zu halten, skaliert aber nicht die eigentliche Zeichnung, um die Skalierung der Bildabmessungen anzupassen. - Wenn du ein
<object>,<embed>oder<iframe>verwendest, um dein SVG einzubetten, ändert das Setzen von Höhe und Breite auf dem<svg>nicht die Größe des Rahmens; du erhältst einfach Scrollbalken innerhalb deines Iframes, wenn das SVG zu groß ist. - Wenn du Inline-SVG verwendest (d. h.
<svg>direkt in deinem HTML5-Code), dann übernimmt das<svg>-Element eine Doppelrolle und definiert sowohl den Bildbereich innerhalb der Webseite als auch innerhalb des SVG. Jede Höhe oder Breite, die du für das SVG mit CSS festlegst, überschreibt die Höhen- und Breitenattribute auf dem<svg>. Eine Regel wiesvg {width: 100%; height: auto;}hebt daher die im Code festgelegten Abmessungen und das Seitenverhältnis auf und gibt dir die Standardhöhe für Inline-SVG. Diese wird, wie oben erwähnt, je nach Browser entweder 150px oder 100vh sein.
Also vergiss height und width. Du möchtest tatsächlich nicht die exakte Höhe und Breite festlegen, sondern möchtest, dass sich das SVG an die in CSS festgelegte Breite und/oder Höhe anpasst. Was du möchtest, ist, ein Seitenverhältnis für das Bild festzulegen und die Zeichnung so skalieren zu lassen, dass sie passt. Du möchtest eine viewBox.
Das viewBox-Attribut
Die SVG viewBox ist eine ganze Menge Magie in einem kleinen Attribut vereint. Sie ist das letzte Puzzleteil, das Vektorgrafiken zu Scalable Vector Graphics macht. Die viewBox tut viele Dinge
- Sie definiert das Seitenverhältnis des Bildes.
- Sie definiert, wie alle Längen und Koordinaten innerhalb des SVG skaliert werden sollen, um den gesamten verfügbaren Platz auszufüllen.
- Sie definiert den Ursprung des SVG-Koordinatensystems, den Punkt, an dem x=0 und y=0 ist.
Die viewBox ist ein Attribut des <svg>-Elements. Ihr Wert ist eine Liste von vier Zahlen, getrennt durch Leerzeichen oder Kommas: x, y, Breite, Höhe. Die Breite ist die Breite in Benutzereinheiten/px-Einheiten, innerhalb des SVG-Codes, die auf die Breite des Bereichs skaliert werden soll, in den du dein SVG zeichnest (in SVG-Terminologie das Viewport). Ebenso ist die Höhe die Anzahl der px/Koordinaten, die auf die verfügbare Höhe skaliert werden sollen. Selbst wenn dein SVG-Code andere Einheiten verwendet, wie Zoll oder Zentimeter, werden diese ebenfalls so skaliert, dass sie mit der durch die viewBox geschaffenen Gesamtgröße übereinstimmen.
Die x- und y-Zahlen geben die Koordinate im skalierten viewBox-Koordinatensystem an, die für die obere linke Ecke des SVG-Viewports verwendet werden soll. (Koordinaten nehmen von links nach rechts und von oben nach unten zu, genauso wie bei der Identifizierung von Seitenpositionen in JavaScript). Für einfache Skalierung kannst du beide Werte auf 0 setzen. Die x- und y-Werte sind jedoch für zwei Zwecke nützlich: um ein Koordinatensystem mit einem Ursprung zu schaffen, der in der Mitte der Zeichnung zentriert ist (dies kann die Definition und Transformation von Formen erleichtern), oder um ein Bild enger zuzuschneiden, als es ursprünglich definiert war.
Einige Beispielwerte für viewBox
viewBox="0 0 100 100": Definiert ein Koordinatensystem von 100 Einheiten Breite und 100 Einheiten Höhe. Anders ausgedrückt: Wenn dein SVG einen Kreis enthält, der in der Grafik zentriert ist und einen Radius von 50 Pixeln hat, würde dieser die Höhe oder Breite des SVG-Bildes ausfüllen, selbst wenn das Bild im Vollbildmodus angezeigt wird. Wenn dein SVG ein Rechteck mitheight="1in"enthält, würde es auch fast den ganzen Bildschirm ausfüllen, da 1 Zoll = 96 Pixel in CSS entspricht und alle Längen gleich skaliert werden.viewBox="5 0 90 100": Ähnliche Ansicht, aber um 5 % von links und rechts beschnitten, so dass die Gesamtbreite = 90 Einheiten und die x-Koordinate links = 5 ist.viewBox="-50 -50 100 100": Eine Ansicht mit der gleichen Skalierung, aber jetzt mit der oberen linken Ecke mit den Koordinaten (-50, -50). Das bedeutet, dass die untere rechte Ecke die Koordinaten (+50, +50) hat. Jede Form, die bei (100, 100) gezeichnet wird, wird weit außerhalb des Bildschirms liegen. Wenn du einen Kreis zeichnen wolltest, der den gesamten Bildbereich ausfüllt, wäre er bei (0, 0) zentriert.
Sobald du deiner <svg> eine viewBox hinzufügst (und Editoren wie Inkscape und Illustrator fügen sie standardmäßig hinzu), kannst du diese SVG-Datei als Bild oder als Inline-SVG-Code verwenden, und sie wird perfekt skaliert, um sich an jede von dir vorgegebene Größe anzupassen. Allerdings wird sie immer noch nicht ganz wie jedes andere Bild skaliert. Standardmäßig wird sie nicht gestreckt oder verzerrt, wenn du ihr Abmessungen gibst, die nicht mit dem Seitenverhältnis übereinstimmen. Stattdessen wird die Skalierung angepasst, um das im Code definierte Seitenverhältnis beizubehalten.
Das preserveAspectRatio-Attribut
Das viewBox-Attribut hat einen Sidekick, preserveAspectRatio. Es hat keine Auswirkung, es sei denn, eine viewBox existiert, um das Seitenverhältnis des Bildes zu definieren. Wenn eine viewBox vorhanden ist, preserveAspectRatio beschreibt, wie das Bild skaliert werden soll, wenn das Seitenverhältnis der viewBox nicht mit dem Seitenverhältnis des Viewports übereinstimmt. Meistens funktioniert das Standardverhalten ziemlich gut: Das Bild wird skaliert, bis es sowohl Höhe als auch Breite ausfüllt, und es wird innerhalb jedes zusätzlichen Raums zentriert.
Genau wie viewBox enthält preserveAspectRatio viele Informationen in einem einzigen Attribut. Das Standardverhalten kann explizit mit preserveAspectRatio="xMidYMid meet" eingestellt werden. Der erste Teil, xMidYMid weist den Browser an, den skalierten viewBox-Bereich sowohl in der x- als auch in der y-Richtung innerhalb des verfügbaren Viewport-Bereichs zu zentrieren. Du kannst Mid durch Min oder Max ersetzen, um die Grafik bündig an einer Seite oder der anderen auszurichten. Achte jedoch auf die Kamelhöcker-Schreibweise: SVG ist XML und daher Groß-/Kleinschreibungsempfindlich. Das x ist klein geschrieben, aber das Y ist groß geschrieben.
Die zweite Hälfte des Standardwerts preserveAspectRatio, meet, ist der Teil, der dem Browser sagt, er soll die Grafik skalieren, bis sie sowohl Höhe als auch Breite ausfüllt. Dies ist bei CSS-Hintergrundbildern äquivalent zu background-size: contain;. Der alternative Wert für SVG ist slice (äquivalent zu background-size: cover;). Ein slice-Wert skaliert das Bild so, dass es sich an die großzügigere Dimension anpasst, und schneidet das Zusätzliche ab. Außer, dass es nicht unbedingt das Zusätzliche abschneidet; das hängt vom Wert der overflow-Eigenschaft ab.
Wenn du möchtest, dass jedes Bild in den von dir vorgegebenen Dimensionen zentriert wird, anstatt gestreckt oder verzerrt zu werden, ermöglicht dir die neue CSS-Eigenschaft object-fit, dies auch mit anderen Bildtypen zu tun.
Es gibt auch die Option preserveAspectRatio="none", um dein SVG genau wie ein Rasterbild zu skalieren (aber mit viel besserer Auflösung), indem es sich an die von dir vorgegebene Höhe und Breite anpasst oder verzerrt.
Wie man SVG an eine bestimmte Größe anpasst (ohne das Bild zu verzerren)
Die wahrscheinlich häufigste Anforderung ist, dass sich ein SVG-Icon an eine bestimmte Größe anpasst, ohne Verzerrung. Das viewBox-Attribut ist hierfür eigentlich alles, was du brauchst, obwohl du preserveAspectRatio verwenden kannst, um die Ausrichtung anzupassen.
Wie bereits erwähnt, enthält deine SVG, wenn du sie in einem Grafikeditor erstellst, wahrscheinlich bereits eine viewBox. Möglicherweise möchtest du die viewBox jedoch anpassen, um die Positionierung genau richtig hinzubekommen. Die Topf-des-Goldes-Grafik hat für die restlichen Beispiele eine viewBox="0 0 60 55" erhalten. Das lässt etwas zusätzlichen Platz darum herum; um ein eng beschnittenes Icon zu erstellen, könntest du viewBox="4.5 1.5 51 49" verwenden. Das folgende Beispiel zeigt auch die Auswirkung des Standardwerts preserveAspectRatio, der die Grafik in dem bereitgestellten Raum zentriert
Wie man SVG an die verfügbare Breite anpasst (und die Höhe entsprechend anpasst)
SVG mit einer viewBox wird an die Höhe und Breite angepasst, die du vorgibst. Aber was ist mit der automatischen Größenanpassung? Bei Rasterbildern kannst du width oder height setzen und die andere Seite anpassen lassen. Kann SVG das?
Das kann es, aber es wird kompliziert. Es gibt ein paar verschiedene Ansätze zur Auswahl, je nachdem, wie du dein SVG einbindest.
Option 1: Automatische Größenanpassung des Bildes verwenden
Wenn eine SVG-Datei eine viewBox hat und in einem <img> eingebettet ist, skalieren Browser (fast immer) das Bild, um es an das in der viewBox definierte Seitenverhältnis anzupassen.
Internet Explorer bleibt jedoch der Fluch von SVG. Obwohl er normalerweise gut funktioniert, habe ich display: table-cell verwendet, um die Figuren in einer früheren Version dieses Beispiels anzuordnen, und IE hat die Bilder auf seltsame Weise verzerrt.
Wenn du das Bild komplett automatisch skalierst, wendet Internet Explorer die standardmäßige Standardgröße von 300×150 an. Andere Browser wenden jedoch standardmäßig { width: 100%; height: auto; } an, wenn das Bild eine viewBox hat; dieses Verhalten ist in keiner Spezifikation definiert.
Zusammenfassend lässt sich sagen: Um SVG, das als <img> verwendet wird, automatisch zu skalieren,
- Setze ein
viewBox-Attribut. - Setze mindestens eine der Optionen Höhe oder Breite.
- Platziere es nicht innerhalb eines Tabellenlayouts, wenn du Internet Explorer unterstützen möchtest.
Option 2: CSS-Hintergrundbilder und der padding-bottom Hack
Größtenteils funktioniert die Verwendung von SVG als CSS-Hintergrundbild viel wie die Verwendung in einem <img> (aber mit dem zusätzlichen Vorteil, dass man Raster-Fallbacks für alte Browser definieren kann). Es gibt einige Fehler bei älteren Browsern, die das Bild nach der Konvertierung in Raster skalieren, anstatt davor (d. h. es verpixelt), aber im Großen und Ganzen ist die viewBox alles, was du brauchst.
Allerdings ist die automatische Größenanpassung keine Option für CSS-Hintergrundbilder; schließlich ist das Bild sekundär zum HTML-Inhalt des Elements. Wenn du möchtest, dass das Element exakt das Seitenverhältnis des von dir verwendeten Bildes hat, musst du es ein wenig hacken.
Es gibt eine Auswahl von CSS-Eigenschaften, die es dir ermöglichen, höhenbasierte Attribute basierend auf der verfügbaren Breite anzupassen. Wenn du den border, padding oder margin eines Blocklayout-Elements auf Prozentwerte setzt, werden die Prozente relativ zur verfügbaren Breite des Containers berechnet, selbst für die oberen und unteren Ränder, Abstände und Ränder.
Der beabsichtigte Zweck ist es, gleichmäßig große Ränder und Abstände zu schaffen, auch wenn die Höhe automatisch ist. Aber das ist nebensächlich. Für unsere Zwecke ist der entscheidende Punkt, dass du die Gesamthöhe eines Elements proportional zur Breite anpassen kannst. Mit anderen Worten, du kannst das Seitenverhältnis kontrollieren. Um ein <div> mit 100 % Breite zu erstellen, das exakt dem 4:3-Seitenverhältnis eines Bildes entspricht, das du als Hintergrund verwendest, kannst du Folgendes verwenden
.ratio4-3 {
width: 100%;
background-image: url(image-with-4-3-aspect-ratio.svg);
background-size: cover;
height: 0;
padding: 0; /* reset */
padding-bottom: calc(100% * 3 / 4);
}
Zu beachtende Punkte
- Um die gewünschte Höhe als Prozentsatz der verfügbaren Breite zu erhalten, multipliziere die prozentuale Breite mit dem gewünschten Höhenfaktor, geteilt durch den gewünschten Breitenfaktor.
- Wenn du Browser unterstützen möchtest, die
calc()nicht unterstützen, musst du die Mathematik selbst (oder mit einem CSS-Präprozessor) durchführen. - Wenn du standardmäßig jedes Element auf
box-sizing: border-boxsetzt, musst du es zurück aufbox-sizing: content-boxsetzen. Wir wollen ja, dass esheight: 0plus Padding ist. - Die Eigenschaft
padding-bottomwird anstelle vonpadding-topverwendet wegen Problemen in IE5. Auch wenn du wahrscheinlich nicht vorhast, IE5 zu unterstützen, kannst du genauso gut konsistent sein. Es wird schließlich derpadding-bottomHack genannt.
Für das Topf-des-Goldes-Bild war das Seitenverhältnis 60:55, was einem unteren Padding von 92 % entspricht. In Aktion sieht das so aus
Option 3: Inline SVG und die neuesten Blink/Firefox-Browser verwenden
SVG-Bilder sind nett, aber in vielen Fällen wirst du Inline-SVG bevorzugen. Inline-SVG reduziert die Anzahl der HTTP-Anfragen, ermöglicht Benutzerinteraktionen und kann durch das CSS deiner Hauptwebseite modifiziert werden. Aber wird es skalieren?
Das wird es, wenn du die neuesten Firefox- oder Blink-Browser verwendest. Setze einfach die viewBox auf dein <svg> und setze eine der Optionen Höhe oder Breite auf auto. Der Browser wird sie so anpassen, dass das Gesamtseitenverhältnis mit der viewBox übereinstimmt. Wunderschön.
Aber wahrscheinlich musst du nicht nur diese Browser unterstützen.
Viele Browser — IE, Safari und Versionen von Opera und Chrome, die vor Sommer 2014 veröffentlicht wurden — skalieren Inline-SVG nicht automatisch. Wenn du nicht sowohl Höhe als auch Breite angibst, wenden diese Browser ihre üblichen Standardgrößen an, die, wie bereits erwähnt, je nach Browser unterschiedlich sind. Das Bild wird skaliert, um in diese Höhe oder Breite zu passen, und lässt wieder zusätzlichen Weißraum darum herum. Auch hier gibt es Inkonsistenzen, was passiert, wenn du sowohl Höhe als auch Breite auf auto lässt.
Die Lösung ist wieder der padding-bottom Hack, um das Seitenverhältnis selbst zu steuern. Der einfachste Ansatz, der sowohl für Inline-SVG als auch für <object>, <iframe> und andere ersetzte Elemente wie <video> funktioniert, ist die Verwendung eines Container-Elements.
Option 4: Den padding-bottom Hack auf einem Container verwenden
Um einen Container <div> zu verwenden, füge Klassen oder Inline-Stile zum Div hinzu, um ihm das richtige Seitenverhältnis zu geben, wie oben bei der Verwendung eines Hintergrundbildes geschehen. Aber setze auch position: relative auf den Container, damit er zum Referenzrahmen für absolut positionierte Inhalte wird. Dann setze das SVG (oder ein anderes Objekt) auf position: absolute, mit Höhe und Breite von 100 %. Die absolute Positionierung ist erforderlich, damit die Prozente relativ zur Höhe des <div> berechnet werden, einschliesslich des Paddings, und nicht relativ zum nullhohen Inhaltsbereich.
Es sei denn, du hast viele Grafiken mit demselben Seitenverhältnis, ist es normalerweise sinnvoll, das padding-bottom inline zu deklarieren, damit es sich direkt neben der viewBox befindet, die es abgleichen muss
<div class="scaling-svg-container"
style="padding-bottom: 92% /* 100% * 55/60 */">
<svg class="scaling-svg" viewBox="0 0 60 55">
<!-- SVG content -->
</svg>
</div>
.scaling-svg-container {
position: relative;
height: 0;
width: 100%;
padding: 0;
padding-bottom: 100%;
/* override this inline for aspect ratio other than square */
}
.scaling-svg {
position: absolute;
height: 100%;
width: 100%;
left: 0;
top: 0;
}
Der Container-Ansatz funktioniert, aber auf Kosten eines zusätzlichen Wrapper-Elements in deinem Markup. Und es ist auch kein Allzweck-Container: Es ist ein Container, der an das exakte Seitenverhältnis angepasst werden muss, das dein SVG benötigt. Die Dinge werden noch kniffliger, wenn du nicht möchtest, dass er auf volle 100 % skaliert; du benötigst einen weiteren Wrapper <div>, um die gewünschte Breite und andere Positionierungsattribute festzulegen. Ich persönlich würde es vorziehen, alle Informationen über das SVG-Seitenverhältnis im SVG-Code selbst zu belassen. Um dies für Inline-SVG zu tun, musst du dem Browser sagen, dass er ausserhalb der Linien und in das Padding zeichnen soll.
Option 5: Den padding-bottom Hack auf einem Inline <svg>-Element verwenden
Um den padding-bottom Hack zu verwenden, um das Seitenverhältnis des gesamten <svg>-Bereichs zu steuern, wird die offizielle Höhe (im Wesentlichen) Null sein. Mit dem Standardwert von preserveAspectRatio würde die Grafik auf Null skaliert werden. Stattdessen möchtest du, dass deine Grafik die gesamte Breite, die du ihr gibst, ausfüllt und über den Padding-Bereich hinausgeht, den du sorgfältig auf das richtige Seitenverhältnis eingestellt hast.
Auch hier verwende ich gerne Inline-Stile für das padding-bottom-Seitenverhältnis, da es an das viewBox-Attribut angepasst werden muss. Im folgenden Beispiel verwende ich es auch für die anderen Stileigenschaften, obwohl du auch eine Klasse verwenden könntest, wenn du viele Grafiken hast, die die gleichen Effekte benötigen
<svg viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice"
style="width: 100%; padding-bottom: 92%; height: 1px; overflow: visible">
<!-- SVG content -->
</svg>
Dabei gibt es noch ein paar weitere Details
- Die Höhe ist 1px, nicht 0, sonst wird das SVG möglicherweise nicht gezeichnet (Firefox) oder skaliert nicht (Chrome).
- Die
preserveAspectRatioverwendetYMinfür die vertikale Ausrichtung, so dass die Grafik sauber am oberen Rand des<svg>Inhaltsbereichs ausgerichtet ist und in das untere Padding überläuft. - Obwohl
overflow: visiblebei HTML Standard ist, muss es für SVG explizit gesetzt werden.
Wenn du möchtest, dass das SVG auf einen Prozentsatz von weniger als 100 % Breite skaliert wird, denke daran, padding-bottom entsprechend anzupassen. Oder verwende einen Wrapper <div>, um die Größe festzulegen.
Wie man SVG skaliert, streckt und quetscht, um sich exakt an eine bestimmte Größe anzupassen
Obwohl die Beibehaltung des Seitenverhältnisses normalerweise wünschenswert ist, handelt es sich manchmal um ein abstraktes oder flexibles Bild, das du strecken möchtest, um es anzupassen.
Option 1: Prozente verwenden
Eine Möglichkeit, um zu strecken und anzupassen, ist die Verwendung von Prozentwerten für alle Größen- und Positionsattribute im SVG.
Zu beachtende Punkte zu Prozenten und SVG
- Wenn du Prozente zum Strecken und Stauchen verwendest, füge keine
viewBoxhinzu (obwohl du Standardhöhe und -breite angeben kannst). - Einige Längen in SVG sind nicht klar entweder der Höhe oder der Breite zugeordnet; zum Beispiel der Radius eines Kreises. Wenn du in diesen Fällen Prozentwerte verwendest, wird die Länge als geometrisches Mittel (Quadratwurzel der Summe der Quadrate, geteilt durch die Quadratwurzel von 2) des entsprechenden Prozentsatzes von Höhe und Breite berechnet. Dies bewahrt die Beziehung des Satzes des Pythagoras von Diagonalen zu Rechtecklinien, ist aber ansonsten etwas verwirrend.
- Viele Längen in SVG können nicht mit Prozenten angegeben werden, am wichtigsten sind die Koordinaten von
<path>und<polygon>-Elementen.
Option 2: preserveAspectRatio="none" verwenden
Wenn Sie eine flexibel skalierbare SVG-Datei wünschen, die auch SVG-Pfade enthält, benötigen Sie eine viewBox plus preserveAspectRatio="none". Hier ist eine etwas schickere Version dieses Regenbogens mit flauschigen Wolken.
Seien Sie sich bewusst, dass mit preserveAspectRatio="none" alles gleichmäßig gestreckt oder gequetscht wird, so als würden Sie andere Bildtypen ungleichmäßig skalieren. Das bedeutet, dass Kreise zu Ellipsen gestreckt werden und Text verzerrt wird. Um dies zu vermeiden, müssen Sie eine Mischung aus Skalierungsansätzen verwenden.
Teile einer SVG separat skalieren
Die Attribute viewBox und preserveAspectRatio sind unglaublich flexibel. Sobald Sie aufhören, SVG als nur ein weiteres Bildformat zu betrachten, können Sie sich fragen, *wie* Ihre Grafik beim Ändern der Fenstergröße skalieren soll.
Wichtig ist zu erkennen, dass Sie nicht für die gesamte SVG eine einzige viewBox und preserveAspectRatio Option definieren müssen. Stattdessen können Sie verschachtelte <svg>-Elemente verwenden, jedes mit seinen eigenen Skalierungsattributen, um verschiedene Teile Ihrer Grafik unabhängig voneinander skalieren zu lassen. (Sie können diese Attribute auch für <symbol> und <pattern>-Elemente verwenden, und Sie können preserveAspectRatio für andere in Ihre SVG eingebettete Bilder verwenden.) Mit diesem Ansatz können Sie eine Kopfzeilengrafik erstellen, die sich streckt, um ein Breitbilddisplay auszufüllen, ohne übermäßige Höhe einzunehmen.
Ich benutze
<img>anstelle von<svg>und es skaliert perfekt, genau wie ein jpg/png oder andere, was mache ich falsch lolJa, SVG skaliert *tatsächlich* gut, wenn es (a) eine viewBox hat und (b) als <img> verwendet wird. Wenn Sie also immer nur Bilder aus Illustrator/Inkscape exportieren und sie als Bilder verwenden, werden Sie nie die Komplexität sehen – bis Sie versuchen, den Code zu bearbeiten und die viewBox vergessen oder bis Sie versuchen, zu Inline-SVG zu wechseln.
Gut zu wissen, dass ich keine dieser Techniken verpasst habe. :)
Ich habe auch die meisten davon behandelt und mich auf SVG-Koordinatensysteme, die Attribute
viewBoxundpreserveAspectRatiosowie verschachtelte SVGs in einem ausführlichen Leitfaden konzentriert, den ich auf meinem Blog geschrieben habe, falls jemand interessiert ist.Teil 1: Alles über die
viewBoxundpreserveAspectRatio, einschließlich einer interaktiven Demo, um die Konzepte vollständig zu verstehen,Teil 2 handelt von Transformationen, was für dieses Thema nicht besonders relevant ist (es sei denn, Sie möchten Transformationen verwenden, um Elemente innerhalb der SVG zu skalieren), und
Teil 3: alles über das Verschachteln von SVGs, einschließlich der Manipulation der neu erstellten "Viewports".
Ich habe auch über das responsive Gestalten von SVGs mit CSS über Browser hinweg bei Codrops geschrieben, wobei der Padding-Hack und andere für andere Browser erforderliche Hacks verwendet werden (sowohl für Inline-, Referenz- als auch für Hintergrundbild-SVGs).
Schließlich ein fantastischer Artikel! Sehr gut geschrieben. :)
Tolle Links, Sara. Wie ich schon sagte, es hilft oft, ein paar verschiedene Beschreibungen eines Themas zu lesen, bevor alles Sinn ergibt.
Eine Sache, die Sie besprochen haben und die ich nicht erwähnt habe, ist, dass SVG, das als <object> eingebettet ist, in den meisten Browsern wie Bilder automatisch skaliert. Ich hatte <object> nur mit den Attributen height/width getestet, nicht mit viewBox, und sie mit <iframe> gruppiert. <iframe> skaliert jedoch niemals automatisch, und <object> tut dies (wenn es ein viewBox-Attribut hat).
Tolle Infos! Die Padding-Bottom-Höhenkorrektur war genau das, was ich für ein aktuelles Projekt mit einem SVG-Hintergrundelement brauchte. Funktioniert einwandfrei.
Die Verwendung von SVG als Hintergrundbild funktioniert großartig… bis man es wiederholen muss. Ich habe tagelang damit gerungen und egal welchen Browser ich geprüft habe, ein wiederholter SVG-Hintergrund wurde immer unscharf. Tipps dazu wären toll.
@A
Können Sie Beispiele oder Details zu Browsern geben? Ich weiß, dass es in älteren Browsern einige Probleme gibt, aber die neuesten Versionen skalieren alle gut bei den von mir getesteten Beispielen.
Eine Möglichkeit: Wenn Ihr Bild
heightundwidthTags hat, aber keineviewBox, rendern die Browser es möglicherweise (konvertieren es in Pixeldaten) in der im SVG-Format angegebenen Größe und skalieren es dann nach der Skalierung auf Ihrebackground-sizehoch, was zu Unschärfe führen würde.Das geschah überall, wo ich nachgeschaut habe: Chrome/Safari/Firefox auf Mac/mit Retina und die Browser von Android, sowohl nativ als auch Chrome. Möglicherweise stört die hohe Pixeldichte die Dinge? Wenn ich die Hintergrundgröße auf cover oder etwas anderes einstelle, ist es in Ordnung, aber dann kann ich diese nicht wiederholen, da die SVG den gesamten Hintergrund ausfüllt. Ich habe auch verschiedene Dinge ausprobiert, einschließlich dessen, was Sie erwähnt haben, indem ich Breite/Höhe entfernt oder die SVG sehr groß gemacht und ihre Größe reduziert habe. Kein Erfolg. Ich habe schließlich aufgegeben und ein PNG verwendet.
Wie viel Unschärfe reden wir? Große Pixelung oder nur weiche Kanten? Eine Sache bei SVG ist, dass der Browser standardmäßig Linien oder Formen antialiast, die über mehrere Pixel gehen, und dies kann zu leichter Unschärfe führen. Dies wäre bei kleinen, gekachelten Grafiken auffälliger als beim Erweitern des Bildes auf volle Größe. Auf Retina sollte es jedoch *weniger* auffällig sein, daher bin ich mir nicht ganz sicher, ob das Ihr Problem war.
Es gibt eine SVG-CSS-Eigenschaft
shape-rendering: crispEdges, die dem Browser sagt, dass er kein Antialiasing verwenden soll. Es gibt auch Tricks wie das Verschieben Ihrer Grafik um einen halben Pixel, aber das wird nicht immer das beabsichtigte Ergebnis liefern, da tatsächliche Bildschirmpixel nicht immer mit CSS-px-Einheiten übereinstimmen.Großartig, großartig und noch mehr großartig. Ich bin so froh, dass die Unterstützung für SVG immer besser wird, es ist wirklich der richtige Weg mit all den Retina-Displays und es hat mehr Vor- als Nachteile bei der Verwendung.
Danke für einen tollen Beitrag
Großartig… groooooßartig… !!
Ich bin fertig… aber ich hatte das Problem, als ich es angewendet habe, die Größe war nicht fix.
Ich benutze die neueste Version von Chrome auf einem MacBook Pro, um diesen Artikel zu lesen, und einige Teile davon werden falsch angezeigt. Zum Beispiel, wo es heißt "Es wird, wenn Sie die neuesten Firefox- oder Blink-Browser verwenden. Setzen Sie einfach die viewBox auf Ihr", direkt nach diesem Absatz sehe ich nur einen leeren 300x150 px großen Bereich, wo ", und setzen Sie eine von height oder width auf" stehen sollte. Dies liegt wahrscheinlich daran, dass die spitzen Klammern nicht escaped wurden. Toller Artikel, ich LIEBTE ihn, sehr nützlich.
Danke Emma — und Entschuldigung an alle, die den Beitrag gerade lesen und völlig verwirrt sind. Ich hatte Schwierigkeiten, das Escaping von Code richtig hinzubekommen, und beim Beheben dieser kleinen ungeescipeten Zeichen habe ich die Bereinigungsroutine von WordPress ausgelöst, die jeden Code löscht, den sie nicht mag. Ich arbeite daran.
Gute Arbeit. Ich hatte ein paar Probleme mit der Größe und Skalierung von SVGs. Ich werde diesen Artikel auf jeden Fall als Referenz aufbewahren. Danke.
Ich füge die viewBox auf dem Symbol-Element hinzu. Dann füge ich meine Icons wie folgt ein:
Diese Icons skalieren nur nach den Standardregeln. Die einzige Möglichkeit, sie richtig skalieren zu lassen, ist, die
viewBoxjedes Mal auf dassvg-Element zu verschieben, wenn ich das Icon verwende, was irgendwie nervt. Ist es möglich, die Breite automatisch zu skalieren, wenn eine bestimmte Höhe angegeben ist, ohneviewBoxfür jeden Gebrauch zu wiederholen?Christian
Leider funktioniert das SVG-Layout von außen nach innen, es passt sich nicht automatisch an den Inhalt an.
Das Setzen der viewBox auf dem <symbol> funktioniert gut, wenn Sie möchten, dass alle Ihre Icons die gleiche Höhe und Breite haben, die in CSS festgelegt sind. Das <use> nimmt standardmäßig 100% der SVG ein, und die viewBox des Symbols positioniert die Icon-Grafik innerhalb dieses Bereichs.
Wenn Sie die Höhe oder Breite des Icons automatisch skalieren möchten, müssen Sie jedoch die Eigenschaften der <svg>-Element selbst steuern, nicht die des Symbols.
Richtig, das habe ich mir gedacht. Ich hatte gehofft, Sie kennen eine esoterische Funktion, die ich verwenden könnte, um das zum Laufen zu bringen :) Danke!
Muchas Gracias, Excelente Articulo
(Vielen Dank, großartige Arbeit)
Großartige Lektüre!
Ich benutze immer noch das img-Tag, aber eine großartige Referenz, danke.
Vielen Dank, Amelia, da dies genau das ist, was ich brauchte. Vermutlich haben andere das auch gebraucht :) um uns mit SVG voranzubringen. Zu bedenken, dass es ein "Dokument" ist, wird auch hilfreich sein.
Ich verwende Inline-SVG als Möglichkeit, einzelne Teile einer Grafik interaktiv zu gestalten. Die meisten meiner Bilder sind höher als breit (im Allgemeinen nach den Abmessungen 8,5x11). Frustriert über den leeren Raum auf beiden Seiten beim Skalieren, habe ich eine jQuery-Funktion geschrieben, um sie durch Setzen der Breite des übergeordneten Divs (das overflow-x: hidden hat) auf die (skalierte) Breite des inneren SVG (+3 px zur Sicherheit) zu "beschneiden". Mit den explizit deklarierten Abmessungen der ursprünglichen SVG berechne ich die skalierte Breite.
Diese Funktion führe ich beim Laden der Seite und jedes Mal aus, wenn ein weiteres SVG dynamisch zum Dokument hinzugefügt wird. Es ist weniger als ideal, aber es funktioniert für meine Zwecke.
Ich benutze immer noch das img-Tag, aber eine großartige Referenz, danke.
Zuvor wusste ich das nicht. Danke, dass Sie die großartigen Informationen geteilt haben.
Ich werde es versuchen!
Diese Lösungen haben bei mir nicht funktioniert. Meine SVGs waren dynamisch generierte Tortendiagramme. Ich füge sie als eigenständige Bilder in Seiten ein.
Ich kann die viewBox nicht einstellen, weil ich ein schönes Diagramm für alle Größen anzeigen möchte.
Ich habe alle verwandten Beiträge auf stackoverflow.com gelesen und dieser Beitrag übertrifft alle. Mein Problem bleibt jedoch. Irgendwelche Vorschläge, bitte.