-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Built-in support for respecting the prefers-reduced-motion
flag with animations/transitions
#5346
Comments
All animations/transitions in svelte are done through pure css, simply add the following to your global style sheet @media (prefers-reduced-motion: reduce) {
* {
animation-delay: 0ms !important;
animation-duration: 1ms !important;
}
} |
All animations/transitions in svelte are not done through pure css. Tweening is VERY much not done though css. The entire motion package isn't CSS |
import { spring as svelte_spring, tweened as svelte_tweened } from "svelte/motion";
import { writable } from "svelte/store";
const reduce_motion = matchMedia("(prefers-reduced-motion: reduce)").matches;
export const spring = reduce_motion ? writable : svelte_spring;
export const tweened = reduce_motion ? writable : svelte_tweened; That's honestly as far as you'll get in terms of support for that feature given the constrains set by the v3 design |
I'm glad this was here - I was drafting a separate issue. Svelte Transitions don't respect
|
This blog post was suggested on Discord by @geoffrich. It has strategies (some similar to above) and also discusses the reasoning behind doing this. I know @Rich-Harris has spoken about the importance of supporting developers to do that right thing when it comes to a11y and I wonder if this is within that scope? Blog Post |
Fresh off a Svelte Summit talk about this very topic, I have some thoughts! I agree that Svelte has a responsibility to do something here, since it includes animation as part of its core library. However, I don't think it should be prescriptive as to how it respects a request for reduced motion. Svelte should not:
There's too much nuance in designing animation to make the right choice for every app. How to handle reduced motion is a design question, and there won't be a hard rule the framework can implement that will work for everyone. Instead, I think the framework should document the need to respect reduced motion in the relevant tutorial sections and docs. While In addition, I think we should include a built-in way to detect if reduced motion is enabled or not. Animation libraries like framer motion already do this with the useReducedMotion hook. While the actual code to do this in Svelte via a custom store is minimal, making it part of the core library would reduce friction and make it easy for developers to do the right thing. Ideally, devs would be able to do something like this... <script>
import { reducedMotion } from 'svelte/motion';
import { fly } from 'svelte/transition';
let show = false;
</script>
<label><input type="checkbox" bind:checked={show}> Show/hide</label>
{#if show}
<h1 transition:fly={{y: $reducedMotion ? 0 : 400}}>Hello world!</h1>
{/if} Let me know what you think of this approach. I think it's another way Svelte can show its commitment to a11y. I'd be happy to put together a PR if I get positive signals on this. |
+1 to not switching fly to fade (or something else) by default if we detect reducedMotion. But i wonder if we can do more than providing tools people need to implement themselves. Wild ideas, tear them apart if not feasible 1) add compile time warnings to motionful transitions without a fallbackSo people are warned when they neglect reducedMotion (similar to some a11y warnings we already have) 2) add a generic way to select a different transition on reduced-motionSo people have tools to add their own use-case aware fallback when needed <script>
import { fly, fade, none } from 'svelte/transition';
let show = false;
</script>
<label><input type="checkbox" bind:checked={show}> Show/hide</label>
{#if show}
<h1 transition:fly={{y: 400}} transitionReduced:fade={{opacity:1}} >Hello world!</h1>
{/if}
{#if show}
<h1 transition:fly={{y: 400}} transitionReduced:none >Hello world!</h1>
{/if} 3) implement default transitions that fall back to fade or none on a separate "reducedMotionAware" namespaceAs a turn-key solution that fits most use-cases to make it as simple as possible to adopt. <script>
import { flyOrFade as fly } from 'svelte/transition/reducedMotionAware';
// or import { flyOrNone as fly } from 'svelte/transition/reducedMotionAware';
let show = false;
</script>
<label><input type="checkbox" bind:checked={show}> Show/hide</label>
{#if show}
<h1 transition:fly={{y: 400}}>Hello world!</h1>
{/if} This would allow people to just swap out an import and be done, no other code changes needed. |
Fwiw, I like the 2nd approach the best. Warnings (# 1) become easier to ignore the more there are of them, and there are many circumstances which require no a11y attention (e.g., exploratory coding). Exposure in such circumstances is likely to desensitize us to such warnings, rather than prompting action. (Not saying that all warnings are bad…just that they're rarely an ideal solution. The alternative motion library approach (# 3) seems too heavy-handed to meet real-world needs. As @geoffrich points out above, and in his excellent Svelte Summit talk, simply turning off animations when
I also like Geoff's |
Thanks for your thoughts, @dominikg and @clozach. Adding warnings (option 1) is a good thought, though I'm a little hesitant since I don't think we could perfectly determine whether or not to show a warning. For example, using Add a /reducedMotionAware namespace is also interesting, though that still puts Svelte in the position in determining what the fallback should be. I do appreciate the desire to make this simple for users, but I think it makes too many decisions (what the fallback should be) that should be left to individual apps. I find the e.g. consider this:
Even if we did have a modifier for it, I still think there's value in exposing the underlying store to give the user even more control. For example, you could then tweak individual parameters on the transition based on the store instead of adding In summary, I'm now proposing the following:
I expect more discussion to be needed around adding a new modifier. I think these could land in separate PRs -- having the store would deliver value if the modifier behavior is still being worked out. |
I think having additional directives would have the added benefit of allowing for helpful tooling in the IDE. There could be some form of hint suggesting that a user add these directives in certain instances. Not sure if it muddies things, but this tip could show only when the transition met certain thresholds. This introduces other issues though, and likely a universal solution (not case/criteria-based) would be more elegant. Regardless, having the option to implement alternate transitions in-line like this is developer-friendly. |
Svelte does not handle when reduced motion is preferred, see: sveltejs/svelte#5346. Because it seems that the incoming transition directive can not be added conditionally (except for by rendering the element conditionally, I use the hack to set animation duration to 0, which makes it un-perceivable.
A simple implementation idea:
with something like |
Honorable mention: https://github.com/ghostdevv/svelte-reduced-motion |
* feat: provide `MediaQuery` / `prefersReducedMotion` closes #5346 * matches -> current, server fallback * createStartStopNotifier * test polyfill * more tests fixes * feedback * rename * tweak, types * hnnnggh * mark as pure * fix type check * notify -> subscribe * add links to inline docs * better API, more docs * add example to prefersReducedMotion * add example for MediaQuery * typo * fix example * tweak docs * changesets * note when APIs were added * add note * regenerate --------- Co-authored-by: Rich Harris <[email protected]>
Is your feature request related to a problem? Please describe.
I was thinking about new ways to honor a user's request to have a less frustrating experience with animations and eventually wondered if this flag is something Svelte itself could (whether as default on or default off) "respect."
Describe the solution you'd like
If Svelte respected
prefers-reduced-motion
out of the box, it could opt-out of any transitions or animations automatically without extra effort on the developer's part. Alternatively, this could be a flag to the various animation features that signal whether they should skip an animation instruction ifprefers-reduced-motion
is on.Describe alternatives you've considered
I've done this in the past manually (in
three.js
/WebGL land) so I think it's certainly doable by the developer if left to their own devices, and can be done today in Svelte without formal support from the library.How important is this feature to you?
I've always appreciated how Svelte helps developers do the right thing, and tries to lessen the pain of the "right thing" if you were left to coding it yourself. If a user is making the request to not have gratuitous or potentially harmful animations, I believe we should do whatever we can to respect that. In my opinion, this feels like a prime candidate for Svelte to encourage and enable the humane choice of respecting the user's request.
The text was updated successfully, but these errors were encountered: