Check out a free preview of the full Accessibility in JavaScript Applications course

The "Unobtrusive Motion" Lesson is part of the full, Accessibility in JavaScript Applications course featured in this preview video. Here's what you'd learn in this lesson:

Marcy describes methods of making web animations more accessible, including the CSS media query prefers-reduced-motion, content warnings, and the JavaScript matchMedia method.


Transcript from the "Unobtrusive Motion" Lesson

>> Marcy Sutton: Let's talk about some motion in animation, because with a lot of the interactivity that we're adding to sites, the delight that our design teams are lovingly asking us to add, can be unsafe for people with certain impairments, disabilities. People who are motion sick have sensitivity to a lot of animating things on the Internet.

Autoplaying videos come to mind, and we can cause actual harm to people if we aren't more careful with our animation. Fortunately, we have a really awesome tool for this now in CSS called prefers-reduced-motion. It's a CSS media query that we can use to change how our animations display depending on an operating system level preference.

We can also do things to help the situation with motion by adding more controls to our interfaces, so regardless of support for something like prefers-reduced-motion, if we add playback controls to give the user more control over interfaces, and it should say opt-out for autoplay, like let the user opt-in, if they want something autoplayed.

Don't just like put autoplay on everything. That can be a difficult conversation to have with some people at your company sometimes, so I definitely get that, but this is where, if we can use tooling, and user preferences, we can start to make safer interactivity. And there's a great article linked here on the site about your interactive is making me sick, especially for people who work at news organizations, like a New York Times, or Public Radio, you get a lot of interactives that are really thoughtfully created, and they maybe they weren't thinking about motion sickness or motion sensitivity.

So it's good to read more about that. I have an animation, I have to give you a content warning, like that's another thing you could do, if you have something that's flashing, adding a content warning. Maybe you don't show it, or you don't animate it until the users like, okay, that's fine, because if I want to animate this, I'm going to open it up on code pen.

And actually, I know what's happening here. So I have prefers-reduced-motion turned on on my machine, so it's not animating, which is cool. So if I go to my preferences, System Preferences on the Mac, and I go to the Accessibility-Display, there is this setting here called Reduce motion, and if I turn that off, it should start animating if this is working properly.

>> Speaker 2: You didn't hit the button to it.
>> Marcy Sutton: And I have a toggle button. Okay, so there were two things happening here. This interface uses reduced motion and local storage. So I've obviously interacted with this before, because it was turned off, and thank you [LAUGH] for the tip.

So I added a toggle button here, and if the user preference, I'm going to turn the animation off, if I change this reduce motion, I can react right away to turn it off, and I'm using that media query to hide that toggle button as well. So with CSS, I can do some pretty cool things to turn animation on and off.

I don't want to leave that up here too long. But what I like about that is it gives the user multiple ways to control it, including this toggle button, which would work in every browser. It doesn't depend on support for prefers-reduced-motion. So here's what the media query looks like.

You say @media (prefers- reduced-motion:, and then you can add different qualifiers here. I'm saying : reduce, so (prefers-reduced-motion: reduce), and then I can target any CSS classes that have animation or transitions applied to them, and turn them off. And it helps, like, if you have crafted animation through your application, it's good to kind of fine tune your turning off of it, because it's like a big blanket, turn it off for everything hammer doesn't always work that well.

There's also a JavaScript API for this. You can use match media to match that CSS media query. You can technically do that for any media query. But then I can add a listener. So I've got the motion query for match media. I can add a listener, so if it changes I can go and adjust the animation, which if my styles are coming from JavaScript for some reason, that might be a nice tool to use.

And some places you can learn more about this or the WebKit guide, cuz this was originally proposed by WebKit, and then the Mozilla Developer Network docs. So for a reduced-motion demo I've got, I'm going to go back to my app and I've got an animation section here with my two furry friends, Rainier and Bagley, and I've got this one on the left that's the completely inaccessible one.

It only works with a hover, so that has other problems, but the Bagley one I can skip down here, and I've changed that one enough so that it's actually keyboard interactive, so it's got a button wrapping it, and if I hit Enter, it will open that animation and send focus to the close button.

So the one with Rainier doesn't even have a close button, so a keyboard user can't even get to this Twitter link back here. He does not have a Twitter account, but if he did a keyboard user wouldn't be able to get to it from this link, and this was taken from, kind of repurposed from a real web.

So these interactivity examples where they only work with a mouse, they come up in real life. So for this one I'm just gonna go at a media query to change that kind of like scaling motion to be more of a fade in and fade out. So for this one it is in this animation, so I've got some CSS here.

To turn, no, that's even a different one. It's card flip. Sorry, [LAUGH] card flip is the one that I'm actually going to go change, and this is a mostly accessible component, it's better than the one in the bad. There's a card flip in here too. And the fix for this that I'm gonna add is just right at the bottom in the CSS.

So if I go look in here for, so I've got transitions, there's using some vendor prefixes here, there's a few, I think that's pretty much it, there's no animation. But you can just kind of go search around, what's animating, what do I need to turn off? And in this case, I'm just gonna go down here.

I'm gonna say @media (prefers-reduced-motion: reduce), and in here, I can go and target, I think it's team-content-overlay. Did I see that? There it is, team-content-overlay. So it's transitioning everything. Everything that will be animatable that is changing when I add this active class, which I'm toggling with JavaScript. So some of the animatable properties here are margins, max height, opacity, and so this transition is just easing, animating anything that is changing that is animatable.

So that's what I'm going to turn off. I'm just going to say transition: none. So inside of the selector I'm just going to say transition: none, and sometimes you might need a bigger hammer and saying, !important. Don't recommend that most of the time, but if you really want to turn off animation, like I think the user would appreciate that working, so I wouldn't recommend that all the time, and I don't think I need it in this case, but if specificity is tripping you up or something I think a reduced motion media query is an acceptable place to do that.

>> Speaker 3: More of a comment, if you don't mind.
>> Marcy Sutton: Sure.
>> Speaker 3: There's an article on CSS Tricks about this, and it's recommended to change the animation duration to like 0.001 milliseconds so that any SVG that builds up, and it's like a mini video-
>> Marcy Sutton: Yeah.
>> Speaker 3: Actually loads otherwise it would nothing, nothing would load.

>> Marcy Sutton: Yes.
>> Speaker 3: So that was something that people found.
>> Marcy Sutton: That is a great point. So I do wanna pull up this other one. Sorry for the flashing. So this one actually has, I've turned off the transition, and then I'm replacing the the styles with something else, so there's some circles in here.

If I go to so there's these pulsing styles here, and this no animate, I'm using a mixin in SAS, and this one I am turning on and off if you click that button, or if you use the media query, which is why I like SAS, I could make something reusable and call it from two different use cases.

But in this one I'm saying animation: none !important, and then giving it something else, because otherwise, yeah, it was coming up blank, because it was growing from zero, and there was nothing to stop on. It was just blank. So yeah, depending on your animation, yeah, maybe you want to play with animation delay or duration.

Maybe you want to replace it with some other CSS styling or something, so yeah, you can play with that. I think from its simplest, just turning stuff off should work. So I'm going to go back over here to my little Bagley demo, and I have not, I think I turned reduced-motion off.

So now it's just open, closed, there's no scaling and going back down, and that was a big thing with iOS. When they had the scaling effect that was making people sick, and that moving motion, and so these effects now, we can actually do better on the web, which I think is really cool.

So I can turn Bagley's animation on and off. This one I probably could too, even though it's not keyboard accessible, I could add that same CSS.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now