SVG/Tutorials/Einstieg/SVG mit CSS stylen
Einer der großen Vorteile von SVG gegenüber zum Beispiel canvas ist die Möglichkeit SVG-Objekte mit CSS zu formatieren.[1]
Anders als bei HTML, wo die Trennung zwischen Inhalt und Design (mittels CSS) schon lange akzeptiert ist, wurde das Aussehen von SVG-Elementen ursprünglich allein durch XML-Attribute festgelegt.[2] Viele davon sind aber Präsentations- oder Geometrie-Attribute, die Sie auch über CSS notieren können. So wird das SVG-Markup schlanker, verständlicher und kann zentral im Stylesheet geändert werden.
Inhaltsverzeichnis
XML vs. CSS
<circle id="beispiel1"
cx="50"
cy="50"
r="50"
fill="gold"
stroke="steelBlue"
stroke-width="2"
/>
<circle id="beispiel2"
style="cx:50; cy:50; r:50; fill:gold; stroke:steelBlue; stroke-width:2;"
/>
Information: Attribute
SVG ist ein XML-Dialekt. SVG-Dokumente bestehen aus einzelnen Elementen. Diese können entweder zwischen Anfangs- und End-Tag weitere Inhalte haben oder wie ein Kreis als inhaltsleere Elemente mit /> enden.
Diese Elemente erhalten durch Attribute bestimmte Eigenschaften. So muss für einen Kreis ein Radius festgelegt werden, zusätzlich kann er zum Beispiel eine Füllung oder eine id erhalten.
Mit CSS ist dies möglich.
Im ersten Beispiel sind alle Angaben als XML-Attribute deklariert, während im zweiten Beispiel alle Stileigenschaften als Inline-CSS in einem style
-Attribut zusammengefasst wurden.[3]
style
-Attribut haben - wie auch in HTML - Vorrang vor CSS-Angaben, die über CSS Regeln in <style>-Elementen oder in externen Stylesheets gemacht wurden.Noch übersichtlicher ist es, die CSS-Anweisungen in einem style-Element zu notieren:
<svg>
<style type="text/css">
<![CDATA[
circle {
cx: 50;
cy: 50;
r: 50;
fill: gold;
stroke: steelBlue;
stroke-width: 2;
}
]]>
</style>
<circle id="beispiel3" />
</svg>
Es ist egal, wo Sie das style-Element notieren:
- am Anfang des SVG-Abschnitts
- innerhalb eines Definitionsabschnitts
- im head des HTML-Dokuments
Stylesheets, die auf diese Weise in einem Inline-SVG Element erstellt werden, sind gleichrangig mit allen anderen Stylesheets, die im HTML-Dokument verwendet werden. Sie gehen in der Reihenfolge, wie der HTML Parser sie antrifft, in die Kaskade ein und haben entsprechende Spezifität.
>
vorkommen darf (z.B. beim Kindkombinator E > F,
sollten die Stil-Definitionen in CDATA gekapselt werden.SVG-Grafiken werden durch die MediaWiki-Software nicht direkt gerendert.
Es werden als Fallback für ältere (mittlerweile ausgestorbene) Browser Vorschau-Grafiken im png-Format erstellt. Dieses Skript benötigt die in HTML5 eigentlich nicht mehr notwendige Angabe
type="text/css"
, damit die style-Festlegungen berücksichtigt werden.<img>
-Element einbetten, können Sie sie aus dem HTML heraus mit CSS nicht beeinflussen. Eine solche Grafik stellt ein Standalone-SVG dar, das ein eigenständiges DOM besitzt und daher eigene Stylesheets braucht.Präsentationsattribute mit CSS gestalten
Um SVG-Elemente auszuwählen, können Sie fast alle Selektoren sowie dynamische Pseudoklassen :hover, :active und :focus und strukturelle Pseudoklassen wie first- und last-child verwenden und für die Präsentationsattribute CSS-Regeln festlegen.
Eigentlich kennen Sie die meisten Präsentationsattribute bereits aus HTML und CSS. Andere wie die Geometrie-Attribute werden im Anschluss erklärt.
Hauptartikel: SVG/Attribut/Präsentationsattribute
Farben
Sie haben schon im letzten Kapitel gesehen, dass Objekte in SVG mehr Gestaltungsmöglichkeiten haben:
In der HTML-Welt haben Block-Elemente einen Hintergrund und Rand, Text jedoch nur eine Textfarbe color. In SVG wird jedes Objekt, ob Grundform, Pfad oder Text gerendert, indem es mit fill gefüllt oder mit einer Randlinie versehen wird. Dabei gibt es viel mehr Möglichkeiten zur Gestaltung dieser Eigenschaften.
* {
stroke: steelBlue;
stroke-width: 5;
}
path {
fill: #c82f04;
}
#quadrat {
fill: gold;
stroke-width: 10;
stroke-opacity: 0.5;
}
Die Grundformen werden über den Universalselektor *
ausgewählt und erhalten mit der stroke-Eigenschaft einen blauen Rand, der mit stroke-width eine Breite von 5
erhält. Eine Angabe zur Füllung fehlt, wodurch der Kreis eine schwarze Füllung erhält.
Das Dreieck über den Typselektor path
ausgewählt und mit fill rot gefüllt (Sollte dort evtl. fill="none" gezeigt werden?)
Das Viereck wird über seine id quadrat
angesprochen und gelb gefüllt. Dort wird die Breite der Randlinie auf 10
erhöht. Da die Randlinie mit stroke-opacity durchscheinend ist, sieht man, dass sich die Randlinie sowohl nach innen als auch nach außen ausdehnt. Obwohl das Quadrat ein width="140"
-Attribut hat, ist es tatsächlich 150 Pixel dimensionslose Einheiten breit.
Füllung
Wie Sie eben gesehen haben, werden Formen in SVG ohne weitere Festlegung schwarz gefüllt. Deshalb muss man immer die fill-Eigenschaft festlegen.
Mögliche Werte für fill sind:
- eine Farbangabe
- die Angabe
none
, Hintergrund wird transparent dargestellt - die Angabe
currentColor
, weist den Browser an, einen festgelegten Standardfarbwert zu verwenden - eine
url(#id)
um ein Muster oder Verlauf zu referenzieren
Dies ist besonders wichtig für Pfade und Polygonlinie mit offenen Pfaden:
.normal {
stroke: steelBlue;
stroke-width: 3;
fill: none;
}
.normal:hover,
.normal:focus {
fill: gold;
}
Aber auch bei sich mehrfach überschneidenden Figuren kann es zu unerwarteten Effekten kommen:
.normal {
stroke: steelBlue;
stroke-width: 3;
fill: gold;
fill-rule: evenodd;
}
#zwei {
fill-rule: nonzero;
}
<svg>
<polygon class="normal" points="100,10 40,198 190,78 10,78 160,198"/>
<polygon class="normal" id="zwei" points="300,10 240,198 390,78 210,78 360,198"/>
</svg>
Geometrie-Attribute
Mit SVG 2 werden die XML-Attribute für Abmessungen (width
, height
bzw. r
, rx
, ry
) und Positionsangaben (x
, y
bzw. cx
, cy
) zu Präsentationsattributen und können nun ebenfalls mit CSS festgelegt und dadurch z. B. durch hover verändert werden.[4]
<circle id="kreis" tabindex="1" cx="100" cy="100" />
<path id="dreieck" tabindex="2" d="M200,30 h140 l-70,140 z" />
<rect id="quadrat" tabindex="3" x="380" y="30" width="140" height="140" />
* {
fill: gold;
stroke: steelBlue;
stroke-width: 3;
transition: all 0.5s ease-out;
}
#kreis {
r: 50px; /* für Firefox */
}
#kreis:hover,
#kreis:focus {
r: 100px;
fill: #c82f04;
}
#dreieck:hover,
#dreieck:focus {
fill: #c82f04;
stroke-width: 40;
stroke: #c82f04;
}
#quadrat:hover,
#quadrat:focus {
fill: steelBlue;
width: 150px;
height: 50px;
}
Alle Elemente erhalten über den Universalselektor *
eine gelbe Füllung, eine schmale blaue Randlinie und eine transition für weiche Übergänge.
Bei :hover
und :focus
ändern die Grundformen ihre CSS-Eigenschaften:
- Der Radius des Kreises wird von 50px auf 100px erhöht
r
keine Einheit; innerhalb von Style-Regeln empfehlen wir aber die Verwendung der Einheit px, weil es Browser-Versionen gab, die die Angabe ohne Einheit nicht akzeptiert haben.- Das Dreieck erhält bei
:hover
mit der Eigenschaft stroke-width einen breiteren Rand. Da der Rand genau auf der Grenze liegt, teilt sich der Rand von 40 so auf, dass er 20px innerhalb und 20px außerhalb des Dreiecks liegt und so Breite und Höhe scheinbar vergrößert. - Das Quadrat hat ein width- und ein height-Attribut. Bei :hover werden die Werte durch die entsprechenden CSS-Regelsätze überschrieben.
:hover
und :focus
beim Aufrufen mit use-Elementen nicht. Verschieben Sie die Kindelemente in das zu animierende Objekt.Siehe auch:
- SVG-Icons, die bei
:hover
und:focus
andere CSS-Festlegungen erhalten - Datenvisualisierung/Balken-_und_Kreisdiagramme
Beispiel, wie die meisten Geometrie-Attribute mit custom properties berechnet werden können! - Lampe auf :hover (Dieses Beispiel arbeitet mit einer externen SVG-Grafik, die mit JavaScript verändert wird.)
- fließender Strom, Lampe und Schatten mit CSS von Sara Soueidan
SVG und Custom Properties
Custom properties ermöglichen es, Werte mehrfach zu verwenden bzw. als Grundlage für Berechnungen zu verwenden. Dies ist auch in SVG möglich - sowohl in den XML-Attributen als auch im Stylesheet:
<style>
.stylesheet {
fill: var(--gold);
stroke: var(--blue);
stroke-width: calc(1.5px * var(--width));
}
svg {
--blue: steelBlue;
--green: #8db243;
--red: #c82f04;
--gold: gold;
--width: 5;
border: thin dotted var(--blue);
}
</style>
<rect ... fill="var(--gold)" stroke="var(--green)" stroke-width="calc(0.5px * var(--width)"/>
<rect ... style="fill: var(--gold);stroke: var(--red);stroke-width: var(--width);"/>
<rect class="stylesheet" x="400" width="90" height="90"/>
SVG hat keinen :root-Selektor, deshalb sind die Farben und die Stärke der Randlinie als custom properties im Regelsatz für das svg-Element notiert und werden …
- im ersten Rechteck, bzw. Kreis als Werte für die XML-Attribute verwendet
- im zweiten Rechteck als Werte im Inline-Style des Style-Attributs und …
- im dritten Rechteck als Werte im Stylesheet verwendet.
Der blaue Rand rechts ist doppelt so stark, da er mit der calc()-Funktion mit 2 multipliziert wurde; das XML-Attribut für das Rechteck mit grünem Rand entsprechend halbiert.
px
ergänzt, da das Ergebnis sonst vom Firefox nicht übernommen wird. Eigentlich ist der Wert für stroke-width ja eine dimensionslose Größe, was Chrome und Safari auch so akzeptieren.Siehe auch:
- Custom properties (CSS-Variablen)
- SVG mit CSS animieren
- SVG/Tutorials/Gruppierungen
- Transform/SVG-Transformationen
SVG und Pseudoelemente
Nur der Einsatz von Pseudolementen wie :after
und :before
ist nicht möglich, da sie in SVG nicht definiert sind. Die Spezifikation ist nicht ganz eindeutig, aber anscheinend werden SVG-Elemente als Grafik wie ein img
behandelt, die keine Pseudoelemente erlauben.[5]
Text in SVG
<text id="eins" x="10" y="120">
TEXT
<tspan dx="-40" dy=".5em" >in</tspan>
</text>
<text id="zwei" x="400 520 620" y="120 170 220">
SVG
</text>
id="eins"
) hat als Inhalt Klartext und ein tspan-Element. Dieses ist mit dem dy-Attribut um 0.5em nach unten verschoben.Der zweite Text mit der id="zwei"
hat mehrere Angaben zu den x- und y-Koordinaten, sodass die einzelnen Zeichen versetzt dargestellt werden.
text {
font-family:serif;
font-size: 120px;
font-weight: bold;
}
#eins {
fill: url(#verlauf);
}
#zwei {
fill: #ffebe6;
stroke: #c82f04;
stroke-width: 3;
font-family: sans-serif;
font-size: 160px;
font-weight: bold;
}
Wie Sie im Beispiel sehen, kann die fill-Eigenschaft viel mehr als eine Farbangabe verarbeiten:
<defs>
<linearGradient id="verlauf">
<stop offset="0.1" stop-color="#306f91 "/>
<stop offset="0.1" stop-color="#dfac20 "/>
<stop offset=".64" stop-color="#dfac20 "/>
<stop offset=".80" stop-color="#306f91 "/>
</linearGradient>
</defs>
Innerhalb des Definitionsabschnitts wird mit linearGradient ein Verlauf festgelegt, der dann im style-Bereich mit seiner id referenziert wird: fill: url(#verlauf);
Der Verlauf hat mehrere stop-Elemente. Da bei den ersten beiden der offset-Wert gleich ist, kommt es zu einem harten Übergang innerhalb des Buchstabens; der dritte und vierte Stop liegen auseinander und sorgen so für einen weichen Übergang.
Hauptartikel: Text-Effekte mit SVG
SVG und die CSS-Kaskade
Wie oben schon erwähnt, überschreiben inline-CSS-Angaben Einstellungen aus externen Stylesheets oder aus dem style-Bereich. Dies entspricht der Spezifität des style-Attributs in HTML.
Während es ziemlich einfach ist, XML-Attribute durch CSS zu überschreiben, benötigen Sie bei Inline-Styles das Schlüsselwort !important.
Auch wenn es scheint, als ob XML-Attribute nun gar nicht mehr verwendet werden müssen, kann es doch empfehlenswert sein, diese zu setzen, um einen FOUSVG (‘Flash Of Unstyled SVG’) zu vermeiden.[6][7][8]
Möglichkeiten und Grenzen
Eigentlich sollten gerade die Präsentationsattribute, die ja Elemente formatieren und die Darstellung festlegen, in einen externen CSS-Bereich ausgelagert werden, um so durch Klassen eine Vielzahl von Objekten zentral zu formatieren.
Andererseits ist z. B. das path-Element eben doch kein immer gleich aussehendes Objekt, sondern eine Möglichkeit eine Vielzahl von verschiedenen Objekten zu erzeugen. Deshalb wäre es nicht zielführend (und auch nicht möglich) das d
-Attribut mit den Pfadangaben ins CSS auszulagern.
Hier gilt es abzuwägen, wie oft ein Attribut wiederverwendet werden soll. Will man einheitliche Linien bei mehreren Elementen, ist eine Festlegung im Stylesheet oder zumindest im oberen style
-Abschnitt zu empfehlen.
Festlegungen, die nur einmal getroffen werden, können als XML-Attribut oder innerhalb eines style-Attributs ihren Platz finden.
Weblinks
- css-tricks: SVG Properties and CSS (13.05.2019)
Quellen
- ↑ W3C: SVG Styling
- ↑ Auch in HTML gibt es Attribute; anfangs auch zur Gestaltung - wie z.B. bei
<body bgcolor="white">
.
Da diese Attribute aus einer Zeit vor der Einführung von CSS 1996 stammen, gilt dort eine etwas abweichende Syntax.
(Siehe: SELF-Forum: schwarzer Hintergrund vom 09.11.2021) - ↑ tutorials.jenkow: SVG and CSS
- ↑ Dirk Schulze auf Twitter: x, y, width and height are #SVG "presentation attributes" in @webkit now.
- ↑ stackoverflow: css-before-on-inline-svg
- ↑ css-tricks: Presentation Attributes vs Inline Styles Chris Coyier (23.12.2016)
- ↑ Sara Soueidan: SVG Style Inheritance and the ‘Flash Of Unstyled SVG’ (01.03.2016)
- ↑ wikibooks.de: CSS: Kaskadierung, Spezifität und Vererbung: Präsentationsattribute