Below is the code that works great in Firefox
, but any attempts to animate the linear gradient's offset attribute in Chrome
ended in nothing.
<svg version="1.1" xmlns=""
xmlns:xlink=""
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="900" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="52%" stop-color="white">
<animate
attributeName="offset"
values="100%;0%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="100%;50%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Below is the code that works great in Firefox
, but any attempts to animate the linear gradient's offset attribute in Chrome
ended in nothing.
<svg version="1.1" xmlns="http://www.w3/2000/svg"
xmlns:xlink="http://www.w3/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="900" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="52%" stop-color="white">
<animate
attributeName="offset"
values="100%;0%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="100%;50%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Also tried using gradientUnits =" objectBoundingBox "
<svg version="1.1" xmlns="http://www.w3/2000/svg"
xmlns:xlink="http://www.w3/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0%" y1="0%" x2="100%" y2="100%" gradientUnits="objectBoundingBox">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="52%" stop-color="white">
<animate
attributeName="offset"
values="100%;0%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="100%;50%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Any solution to this problem will do with: SVG
,css
, javascript
- 1 Report it to Chrome's bugtracker. – Robert Longson Commented Jul 21, 2019 at 7:21
- 1 Intrested in a pure CSS animation? – Temani Afif Commented Jul 21, 2019 at 8:28
-
@Temani Afif I look forward to solving CSS from you, but I’m interested in the animation exactly attribute
offset
– Alexandr_TT Commented Jul 21, 2019 at 8:33 - it's difficult to have exactly the same but we can approximate it like this: jsfiddle/d6kbvx1n ... I am pretty sure we can do better but it need more precise values. – Temani Afif Commented Jul 21, 2019 at 10:01
- @Temani Afif Please post your CSS solution here. – Alexandr_TT Commented Jul 21, 2019 at 10:14
4 Answers
Reset to default 8One solution to this would be using floating numbers instead of percentages, i.e values="1;0;1"
instead of values="100%;0%;100%"
svg{border:1px solid}
<svg version="1.1" xmlns="http://www.w3/2000/svg"
xmlns:xlink="http://www.w3/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="50%" y2="50%" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="dodgerblue"/>
<stop offset=".52" stop-color="white">
<animate
attributeName="offset"
values="1;0;1"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="1" stop-color="gold">
<animate
attributeName="offset"
values="1;.5;1"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Here is an idea with CSS only where you can rely on two gradients and a translation/opacity animation to approximate it. I also considered a little blur effect to have a better transition between gradient.
.box {
border-radius:20px;
width:200px;
height:200px;
position:relative;
z-index:0;
overflow:hidden;
}
.box:before,
.box:after{
content:"";
position:absolute;
bottom:0;
right:0;
width:220%;
height:220%;
animation:translate 2s infinite linear alternate;
}
.box:after {
background:
linear-gradient(to bottom right,dodgerblue 0%,white 40%,gold 60%);
animation-name:translate,show;
opacity:0;
}
.box:before {
background:
linear-gradient(to bottom right,dodgerblue,white 50%,gold 50%);
animation-name:translate,fade;
}
@keyframes translate{
from {
transform:translate(48%,48%);
}
}
@keyframes show{
30%,85% {
opacity:1;
}
}
@keyframes fade{
30%,85% {
filter:blur(8px);
}
}
<div class="box">
</div>
You can always use javascript
for that:
requestAnimationFrame(animateOffsets);
// if this function called as callback of requestAnimationFrame,
// so there are first argument is the time from beginning from scene start
function animateOffsets(t) {
requestAnimationFrame(animateOffsets);
t = t%5000/5000; // will change from 0 to 1 (5 sec)
t = Math.sin(t*Math.PI*2); // will change from -1 to 1
stop1.setAttribute('offset', `${50 + t*50}%`);
}
<svg version="1.1" xmlns="http://www.w3/2000/svg"
xmlns:xlink="http://www.w3/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="60%" y2="60%" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="50%" stop-color="white" id="stop1"/>
<stop offset="100%" stop-color="gold"/>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Gradient attribute offset
animation as background image
<svg version="1.1" xmlns="http://www.w3/2000/svg"
xmlns:xlink="http://www.w3/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<linearGradient id="bgg" x1="479" y1="-345" x2="479" y2="853" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#fff">
<animate
attributeName="offset"
values="0;1;1;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="0;1;1;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
</linearGradient>
<rect x="-45" y="0" width="70%" height="70%" rx="5%" fill="#ACA900" />
<rect x="65" y="80" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
<image x="30" y="100" xlink:href="https://upload.wikimedia/wikipedia/mons/f/fd/Ghostscript_Tiger.svg" width="50%" height="50%" />
</svg>
Radial gradient effects
<svg version="1.1" xmlns="http://www.w3/2000/svg"
xmlns:xlink="http://www.w3/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<radialGradient id="myRadial"
fx="50%" fy="50%" r="80%">
<stop offset="0%" stop-color="gold">
<animate
attributeName="offset"
values="0;1.3;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="100%" stop-color="#EDEDED">
<animate
attributeName="offset"
values="0;1.3;1.3;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
</radialGradient>
<rect x="0" y="0" width="70%" height="70%" rx="5%" fill="#ACC400" />
<rect x="85" y="80" width="50%" height="50%" rx="5%" fill="url(#myRadial)" />
</svg>