I'm trying to get a gradient applied to an SVG rect
element.
Currently, I'm using the fill
attribute. In my CSS file:
rect {
cursor: pointer;
shape-rendering: crispEdges;
fill: #a71a2e;
}
And the rect
element has the correct fill color when viewed in the browser.
However, I'd like to know if I can apply a linear gradient to this element?
Just use in the CSS whatever you would use in a fill
attribute. Of course, this requires that you have defined the linear gradient somewhere in your SVG.
Here is a complete example:
rect { cursor: pointer; shape-rendering: crispEdges; fill: url(#MyGradient); }
2019 Answer
With brand new css properties you can have even more flexibility with variables aka 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; }
Just set a named variable for each stop
in gradient and then customize as you like in css. You can even change their values dynamically with javascript, like:
document.querySelector('#header-shape-gradient').style.setProperty('--color-stop', "#f5f7f9");
Building on top of what Finesse wrote, here is a simpler way to target the svg and change it's gradient.
This is what you need to do:
Assign classes to each color stop defined in the gradient element. Target the css and change the stop-color for each of those stops using plain classes. Win!
Some benefits of using classes instead of :nth-child
is that it'll not be affected if you reorder your stops. Also, it makes the intent of each class clear - you'll be left wondering whether you needed a blue color on the first child or the second one.
I've tested it on all Chrome, Firefox and IE11:
.main-stop { stop-color: red; } .alt-stop { stop-color: green; }
See an editable example here: https://jsbin.com/gabuvisuhe/edit?html,css,output
Here is a solution where you can add a gradient and change its colours using only CSS:
// 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;
}
Thank you everyone, for all your precise replys.
Using the svg in a shadow dom, I add the 3 linear gradients I need within the svg, inside a . I place the css fill rule on the web component and the inheritance od fill does the job.
The first one is normal SVG, the second one is inside a shadow dom.
Here is how to set a linearGradient on a target element:
<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>
Success story sharing
fill
this way:fill: url(../js/gradient.svg#MyGradient);
. Is this the right way?fill: linear-gradient (...)
?"fill
requires a<paint>
which is built around the CSS2<color>
class. In other words, this answer is currently the only way to do it via CSS at the time I am writing this comment. You need to add alinearGradient
element. Lastly, going through the w3 Working Draft for SVG2, it appears support forlinear-gradient
on the fill css rule has not and might not make it into the spec.gradientTransform
attribute)