SVG-Gradient mit CSS

101

Ich versuche, einen Farbverlauf auf ein SVG- rectElement anzuwenden .

Derzeit verwende ich das fillAttribut. In meiner CSS-Datei:

rect {
    cursor: pointer;
    shape-rendering: crispEdges;
    fill: #a71a2e;
}

Und das rectElement hat die richtige Füllfarbe, wenn es im Browser angezeigt wird.

Ich möchte jedoch wissen, ob ich diesem Element einen linearen Farbverlauf zuweisen kann.

Hrishikesh Choudhari
quelle

Antworten:

94

Verwenden Sie im CSS einfach alles, was Sie in einem fillAttribut verwenden würden. Dies setzt natürlich voraus, dass Sie den linearen Gradienten irgendwo in Ihrem SVG definiert haben.

Hier ist ein vollständiges Beispiel:

rect {
    cursor: pointer;
    shape-rendering: crispEdges;
    fill: url(#MyGradient);
}
<svg width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
      <style type="text/css">
        rect{fill:url(#MyGradient)}
      </style>
      <defs>
        <linearGradient id="MyGradient">
          <stop offset="5%" stop-color="#F60" />
          <stop offset="95%" stop-color="#FF6" />
        </linearGradient>
      </defs>
      
      <rect width="100" height="50"/>
    </svg>

Thomas W.
quelle
2
Also habe ich diesen Verlauf in einer separaten Datei erstellt und folgendermaßen verwendet fill: fill: url(../js/gradient.svg#MyGradient);. Ist das der richtige Weg?
Hrishikesh Choudhari
@HrishikeshChoudhari: Ja, das ist richtig, aber Chrome und ich denken, dass Safari auch das Referenzieren von Elementen aus anderen Dateien nicht unterstützt. Ich bin mir nicht sicher über IE9 (kann momentan nicht testen, probieren Sie es einfach aus).
Thomas W
53
An alle, die dies lesen und fragen, "was ist mit fill: linear-gradient (...) ?" fillerfordert eine, <paint>die um die CSS2- <color>Klasse herum aufgebaut ist . Mit anderen Worten, diese Antwort ist derzeit die einzige Möglichkeit, dies über CSS zu tun, wenn ich diesen Kommentar schreibe. Sie müssen ein linearGradientElement hinzufügen . Wenn man den w3-Arbeitsentwurf für SVG2 durchläuft , scheint es, dass die Unterstützung für linear-gradientdie Füll-CSS-Regel es nicht in die Spezifikation geschafft hat und möglicherweise nicht schafft .
Arthur Weborg
Wie kann man in diesem Fall die Richtung ändern?
AGamePlayer
1
@AwQiruiGuo Werfen Sie einen Blick auf MDN (speziell das gradientTransformAttribut)
Thomas W
32

2019 Antwort

Mit brandneuen CSS-Eigenschaften können Sie mit Variablen aka noch mehr Flexibilität haben custom properties

.shape {
  width:500px;
  height:200px;
}

.shape .gradient-bg {
  fill: url(#header-shape-gradient) #fff;
}

#header-shape-gradient {
  --color-stop: #f12c06;
  --color-bot: #faed34;
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" class="shape">
  <defs>
    <linearGradient id="header-shape-gradient" x2="0.35" y2="1">
        <stop offset="0%" stop-color="var(--color-stop)" />
        <stop offset="30%" stop-color="var(--color-stop)" />
        <stop offset="100%" stop-color="var(--color-bot)" />
      </linearGradient>
  </defs>
  <g>
    <polygon class="gradient-bg" points="0,0 100,0 0,66" />
  </g>
</svg>

Legen Sie einfach eine benannte Variable für jede Variable stopim Verlauf fest und passen Sie sie dann in CSS nach Ihren Wünschen an. Sie können ihre Werte sogar dynamisch mit Javascript ändern, wie zum Beispiel:

document.querySelector('#header-shape-gradient').style.setProperty('--color-stop', "#f5f7f9");
Maciej Kwas
quelle
3
Wird im IE nicht unterstützt.
Aoakeson
3
Benutzerdefinierte CSS-Eigenschaften sind sehr lange hier. Wenn jemand noch nicht bereit ist, sie zu verwenden, ist er nie bereit für Änderungen.
Maciej Kwas
1
@ MaciejKwas, du liegst falsch. Alte Browser bleiben nicht für immer, sodass Unternehmen, die jetzt nicht bereit sind, dann bereit sind. Und wenn jemand nicht bereit ist, einen Teil seines Publikums zu verwerfen, bedeutet dies nicht, dass er nicht bereit für Änderungen ist, sondern dass er die Änderungen lieber später nutzt, um ein größeres Publikum zu halten.
Finesse
17
@aoakeson IE ist tot. Lebensende. Edge stirbt ebenfalls, dies ist eine Antwort von 2019, daher sollte der IE nicht zählen. IE kann sich durch Verwendung einer Volltonfarbe elegant verschlechtern.
Ciprian
5
@aoakeson Ich bin erstaunlich überrascht, dass ich 2019 auf diese Art von Reaktion gestoßen bin. Sie wären als Entwickler naiv, wenn Sie davon ausgehen würden, dass SVG-Unterstützung in IE auf dieser Ebene jemals unterstützt wird, geschweige denn ein angehender Entwickler auf SO, der Ihnen aufgebläht ist , polygefüllte Antwort für etwas, das unnötig benötigt wird, wenn Sie den IE unterstützen möchten.
James Martin-Davies
18

Aufbauend auf dem, was Finesse geschrieben hat, ist hier eine einfachere Möglichkeit, das SVG anzuvisieren und seinen Gradienten zu ändern.

Folgendes müssen Sie tun:

  1. Weisen Sie jedem im Verlaufselement definierten Farbstopp Klassen zu.
  2. Zielen Sie auf das CSS und ändern Sie die Stoppfarbe für jeden dieser Stopps mithilfe einfacher Klassen.
  3. Sieg!

Einige Vorteile der Verwendung von Klassen anstelle von :nth-childsind, dass es nicht betroffen ist, wenn Sie Ihre Stopps neu anordnen. Außerdem wird die Absicht jeder Klasse klar - Sie werden sich fragen, ob Sie für das erste oder das zweite Kind eine blaue Farbe benötigen.

Ich habe es auf allen Chrome, Firefox und IE11 getestet:

.main-stop {
  stop-color: red;
}
.alt-stop {
  stop-color: green;
}
<svg class="green" width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <linearGradient id="gradient">
    <stop class="main-stop" offset="0%" />
    <stop class="alt-stop" offset="100%" />
  </linearGradient>
  <rect width="100" height="50" fill="url(#gradient)" />
</svg>

Ein bearbeitbares Beispiel finden Sie hier: https://jsbin.com/gabuvisuhe/edit?html,css,output

kumarharsh
quelle
Der Mangel ist, dass Sie nicht sicher wissen, wie die Namen der Stoppklassen lauten und welche Reihenfolge sie haben. Tatsächlich sind die Lösungen gleich gut, der einzige Unterschied sind die CSS-Selektoren.
Finesse
3
Ich denke, dies ist die beste moderne Antwort auf die Frage der OP.
Elemental
9

Hier ist eine Lösung, bei der Sie einen Verlauf hinzufügen und seine Farben nur mit CSS ändern können:

// JS is not required for the solution. It's used only for the interactive demo.
const svg = document.querySelector('svg');
document.querySelector('#greenButton').addEventListener('click', () => svg.setAttribute('class', 'green'));
document.querySelector('#redButton').addEventListener('click', () => svg.setAttribute('class', 'red'));
svg.green stop:nth-child(1) {
  stop-color: #60c50b;
}
svg.green stop:nth-child(2) {
  stop-color: #139a26;
}

svg.red stop:nth-child(1) {
  stop-color: #c84f31;
}
svg.red stop:nth-child(2) {
  stop-color: #dA3448;
}
<svg class="green" width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <linearGradient id="gradient">
    <stop offset="0%" />
    <stop offset="100%" />
  </linearGradient>
  <rect width="100" height="50" fill="url(#gradient)" />
</svg>

<br/>
<button id="greenButton">Green</button>
<button id="redButton">Red</button>

Finesse
quelle
2

Vielen Dank an alle für Ihre präzisen Antworten.

Mit dem SVG in einem Schattendom füge ich die 3 linearen Verläufe hinzu, die ich innerhalb des SVG innerhalb von a benötige. Ich platziere die CSS-Füllregel auf der Webkomponente und die Vererbung oder Füllung erledigt den Job.

<svg viewbox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
  <path
    d="m258 0c-45 0-83 38-83 83 0 45 37 83 83 83 45 0 83-39 83-84 0-45-38-82-83-82zm-85 204c-13 0-24 10-24 23v48c0 13 11 23 24 23h23v119h-23c-13 0-24 11-24 24l-0 47c0 13 11 24 24 24h168c13 0 24-11 24-24l0-47c0-13-11-24-24-24h-21v-190c0-13-11-23-24-23h-123z"></path>
</svg>

<svg height="0" width="0">
  <defs>
    <linearGradient id="lgrad-p" gradientTransform="rotate(75)"><stop offset="45%" stop-color="#4169e1"></stop><stop offset="99%" stop-color="#c44764"></stop></linearGradient>
    <linearGradient id="lgrad-s" gradientTransform="rotate(75)"><stop offset="45%" stop-color="#ef3c3a"></stop><stop offset="99%" stop-color="#6d5eb7"></stop></linearGradient>
    <linearGradient id="lgrad-g" gradientTransform="rotate(75)"><stop offset="45%" stop-color="#585f74"></stop><stop offset="99%" stop-color="#b6bbc8"></stop></linearGradient>
  </defs>
</svg>

<div></div>

<style>
  :first-child {
    height:150px;
    width:150px;
    fill:url(#lgrad-p) blue;
  }
  div{
    position:relative;
    width:150px;
    height:150px;
    fill:url(#lgrad-s) red;
  }
</style>
<script>
  const shadow = document.querySelector('div').attachShadow({mode: 'open'});
  shadow.innerHTML="<svg viewbox=\"0 0 512 512\">\
    <path d=\"m258 0c-45 0-83 38-83 83 0 45 37 83 83 83 45 0 83-39 83-84 0-45-38-82-83-82zm-85 204c-13 0-24 10-24 23v48c0 13 11 23 24 23h23v119h-23c-13 0-24 11-24 24l-0 47c0 13 11 24 24 24h168c13 0 24-11 24-24l0-47c0-13-11-24-24-24h-21v-190c0-13-11-23-24-23h-123z\"></path>\
  </svg>\
  <svg height=\"0\">\
  <defs>\
    <linearGradient id=\"lgrad-s\" gradientTransform=\"rotate(75)\"><stop offset=\"45%\" stop-color=\"#ef3c3a\"></stop><stop offset=\"99%\" stop-color=\"#6d5eb7\"></stop></linearGradient>\
    <linearGradient id=\"lgrad-g\" gradientTransform=\"rotate(75)\"><stop offset=\"45%\" stop-color=\"#585f74\"></stop><stop offset=\"99%\" stop-color=\"#b6bbc8\"></stop></linearGradient>\
  </defs>\
</svg>\
";
</script>

siehe meinen Test im Codepen

Das erste ist normales SVG, das zweite befindet sich in einem Schattendom.

Roland Gautier
quelle
-4

So setzen Sie einen linearGradient für ein Zielelement :

<style type="text/css">
    path{fill:url('#MyGradient')}
</style>
<defs>
    <linearGradient id="MyGradient">
        <stop offset="0%" stop-color="#e4e4e3" ></stop>
        <stop offset="80%" stop-color="#fff" ></stop>
    </linearGradient>
</defs>
Axelparatre
quelle
Nichts in der Frage impliziert die Verwendung von PHP.
ACJ