CSS can't access/manipulate any SMIL animation related properties
(as specified in an <animate>
element).
But you could check the current preferred motion configuration via JavaScript.
let reducedMotion = window.matchMedia(`(prefers-reduced-motion: reduce)`) === true || window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;
console.log('reducedMotion', reducedMotion)
if (reducedMotion) {
stopSmilAnimations();
}
function stopSmilAnimations(){
let svgs = document.querySelectorAll("svg");
svgs.forEach(svg=>{
svg.pauseAnimations();
})
}
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<circle cx="50" cy="50" r="30" fill="red"/>
<animateTransform
attributeName="transform"
dur="1s"
type="translate"
repeatCount="indefinite"
from="100 -25"
to="-100 25"
/>
</g>
</svg>
If prefers-reduced-motion
is detected you can run a function pausing all svg animations via svg.pauseAnimations()
.
Disabling animations via JS may also be a good approach in terms of accessibility or selective preferences:
Some users may not have set their browser correctly to avoid/minimize animations. A user defined configuration similar to privacy settings or something like a Dark-Mode toggle could immediately change the preferred settings.
Disable animations via display:content
As commented by Kaiido we could disable this animation targeting the <g>
element by applying display:content
to the group.
The rendering will behave as if we had removed the <g>
element from the DOM but keeping it's children. The <animateTransform>
element will lose its target.
svg{
border: 1px solid red
}
g {
display: contents;
}
<svg width="100" height="100" viewBox="0 0 200 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<circle cx="50" cy="50" r="30" fill="red"/>
<animateTransform
attributeName="transform"
dur="1s"
type="translate"
repeatCount="indefinite"
from="100 -25"
to="-100 25"
/>
</g>
<g>
<circle cx="0" cy="50" r="15" fill="blue" stroke="black" stroke-width="1">
<animate
attributeName="cx"
from="0"
to="500"
dur="5s"
repeatCount="indefinite" />
</circle>
</g>
</svg>
As you can see, the first animation is stopped. The 2. is unaffected (still playing) because the <animate>
element is targeting the <circle>
element. So you can't apply this CSS-only approach to all kind of SMIL animations.