Reputation: 35
So I've got this CodePen: https://codepen.io/naregjan/pen/MBzQWp
In it, I've got four rects inside of an SVG frame, and two of them have gradients. I want to transition the stop colours for the gradients on hover, similarly to this pen.
The relevant CSS:
.red{
fill: url(#grad1);
}
.red ~ defs stop{
transition: 1s;
}
.red:hover ~ defs stop:first-child {
stop-color: #ffbbcc;
}
.red:hover ~ defs stop:last-child {
stop-color: #0000ff;
}
And the relevant HTML (the squares are generated via JS; this is via the Chrome Inspector):
<svg id="sqSVG" width="500" height="500">
<rect class="square green" x="135" y="135" width="100" height="100"></rect>
<rect class="square green" x="10" y="135" width="100" height="100"></rect
<rect class="square red" x="135" y="10" width="100" height="100"></rect>
<rect class="square red" x="10" y="10" width="100" height="100"></rect>
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="110%" y2="110%">
<stop offset="0%" style="stop-color:#ff0000"></stop>
<stop offset="100%" style="stop-color:#ffffff"></stop>
</linearGradient>
</defs>
</svg>
I can't figure out what's wrong. It won't just not animate, it won't change the stop colour on hover at all, and I can't figure out what's different from the example I linked. The rects are created before defs and they share a parent, so the selector should work... what am I missing?
In case it's relevant, here's my square-making function:
function makeSquares(){
var svg = document.querySelector("#sqSVG");
var squares = [
{x : "10", y : "10", color: "red"},
{x : "135", y : "10", color: "red"},
{x : "10", y : "135", color: "green"},
{x : "135", y : "135", color: "green"}
];
squares.forEach(sq => {
var newSq = document.createElementNS("http://www.w3.org/2000/svg", 'rect');
newSq.setAttribute("class", "square " + sq.color);
newSq.setAttribute("x", sq.x);
newSq.setAttribute("y", sq.y);
newSq.setAttribute("width", "100");
newSq.setAttribute("height", "100");
svg.prepend(newSq);
});
}
... but I don't think it is, because it won't work while hard-coded in HTML, either. Help?
Upvotes: 3
Views: 1685
Reputation: 101800
As @Kaiido said, you are being thwarted because style
attributes override CSS. So your hover rules were having no effect.
The fix is to change them to attributes. Change
style="stop-color:#ffffff"
to
stop-color="#ffffff"
In addition, you had a typo. </rect
should be </rect>
in the second rectangle.
.red{
fill: url(#grad1);
}
.red ~ defs stop{
transition: 1s;
}
.red:hover ~ defs stop:first-child {
stop-color: #ffbbcc;
}
.red:hover ~ defs stop:last-child {
stop-color: #0000ff;
}
<svg id="sqSVG" width="500" height="500">
<rect class="square green" x="135" y="135" width="100" height="100"></rect>
<rect class="square green" x="10" y="135" width="100" height="100"></rect>
<rect class="square red" x="135" y="10" width="100" height="100"></rect>
<rect class="square red" x="10" y="10" width="100" height="100"></rect>
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="110%" y2="110%">
<stop offset="0%" stop-color="#ff0000"></stop>
<stop offset="100%" stop-color="#ffffff"></stop>
</linearGradient>
</defs>
</svg>
Upvotes: 4