Check out a free preview of the full Enterprise Web App Accessibility (feat. React) course:
The "Accessibility in JS Apps" Lesson is part of the full, Enterprise Web App Accessibility (feat. React) course featured in this preview video. Here's what you'd learn in this lesson:

Marcy discusses accessibility in JavaScript applications, specifically focusing on client-side rendering and routing. They explain the implications of client-side rendering for keyboard and screen reader users and discuss techniques for handling page changes and maintaining accessibility. The instructor also shares their own research on client-side routing and provides recommendations for improving the accessibility of JavaScript-heavy apps.

Get Unlimited Access Now

Transcript from the "Accessibility in JS Apps" Lesson

[00:00:00]
>> Let's switch gears a bit and dive into accessibility in JavaScript applications, something that I have been very passionate about for a long time because I feel like there's a lot to improve in JavaScript-heavy apps. So let's focus on some of the unique aspects, starting with client-side rendering and client-side routing.

[00:00:20] So, when you render your pages using libraries like React, Angular, View, Framework of the week, [LAUGH] often those JavaScript libraries are taking over rendering and routing from the browser. So, replacing one view with another using JavaScript, and there is no page refresh. That has implications, especially for keyboard and screen reader users, often missed, but let's talk about what goes into that.

[00:00:51] Sometimes these apps are doing what's called hydration, where you have content that's pre-rendered on the server, and then there's client side code. Sometimes it's a duplication. Don't love that. But you go from this pre rendered server code, the JavaScript downloads executes, and then they hydrate the pages into interactive versions.

[00:01:13] And so that's pretty popular. Gatsby did that, Next does it, Spelte, among others. You can configure a lot of your libraries and frameworks to render on the server, which is great. It's super cool. At least with things like Astro, they give you the option. Really, obviously, it's pretty cool.

[00:01:31] It's gotten easier for sure to pre render on the server. So this question comes up, do people turn JavaScript off? It's kind of the elephant in the room, we're talking about rendering on the server, talking about a lot of clients like JavaScript, there's been a debate over that for a long time.

[00:01:47] And most of the internet requires it now. I don't know if you've turned off JavaScript and tried to navigate the web recently, but it would be hard. [LAUGH] You're gonna have a bad time probably. And so it is easier to render web apps on the server now than it was a few years ago.

[00:02:05] But we've come to know and expect and users have come to know and expect a certain level of modern interactivity. Anyone that uses Facebook would be upset if it refreshed every time they hit the light button, like that asynchronous posting to a server, updating, I mean, we expect things to be fast and async, so not too many people are turning JavaScript off.

[00:02:30] For accessibility, it is not strictly a requirement that you support node.js. In fact, JavaScript is necessary for stateful ARIA. If you have any ARIA states that you're turning on and off, you have to toggle those with JavaScript and even keyboard events. I mean, sure, you could do a lot with forms, but that's not gonna get to the type of experience that we expect now.

[00:02:54] So JavaScript is not a bad thing. I love JavaScript. It's powerful, it's in every browser. I mean, it's everywhere, right? We can do a lot. It's gotten really good, too. A lot of the features we have now are great. So, for accessibility, JavaScript can be helpful. It also can be the source of a lot of inaccessible apps.

[00:03:16] So, let's talk about the accessibility impacts of JavaScript. So screen readers do look at a page as rendered. So however the page is constructed, whether it's hydrated from the server and then turned into client side code, or if it's totally rendered all in the client with JavaScript, screen readers are going to look at what has been rendered at the end of that process, so it's fine to use JavaScript.

[00:03:43] You do need to consider lower bandwidth networks and people with older devices, but that's not strictly an accessibility issue, it's more usability performance, like those topics start to come up. But this is where accessibility and Performance tend to intersect. So with client-side routing, that is when we take the functionality of page refreshes away from the browser and we let JavaScript replace those views instead.

[00:04:13] So we're replacing one with another. And this has those impacts, as I said, on keyboard users because when you click on something without doing anything about it, and a JavaScript library or a routing library, your focus is just gonna stay there, cuz the page didn't refresh. So for a keyboard user, they might be left there going, did anything happen?

[00:04:33] I clicked that, I didn't hear anything, and maybe it changed the view, if I could see it. But I'm still left on that link, just kind of functionally, that's what happens. And so for a screen reader user, they might have no idea that the page changed. They're clicking, okay, I clicked this link, nothing happened, I didn't hear anything, I have no idea, I'm still on this link, I think it might be broken.

[00:04:58] That's kind of a problem, isn't it? So we need to handle that. And there are some techniques. And I had heard many techniques over the years, including, okay, I'm on this nav link, I hit Enter, I send focus to a heading in the new content area. Okay, that could work, for a screen reader user, That would announce that content.

[00:05:19] It would move me in the new content so I would know something happened. And screen reader users have been happy with that. It's worked fine. If you add tab index of negative one on that heading, you can make sure you catch it with that programmatic focus. He used JavaScript to actually call focus on that element.

[00:05:37] Another technique, very similar is when you're on that nav link and you hit Enter, you send focus to a wrapper element instead of a heading. It's pretty similar except it's gonna announce more than just the heading. So both of those have been recommended. There's other techniques that I've seen in the wild.

[00:05:55] So another technique could be maybe you leave focus Where it was on the nav link, but there's an ARIA live region on the new content. And when it changes, it'll automatically announce it. It kind of like our slide show, when that content changed, it was automatically getting announced.

[00:06:10] I've seen that on sites. You could potentially leave focus where it is and have a separate live region. That's just hidden from view, but it's still rendered and it just says, hey, page change to portfolio page or whatever the new pages. So these are all techniques and they're all floating around.

[00:06:28] I thought, I really wish I had more information on what to recommend. So when I worked at Gatsby, I did some testing with a group called Fable in Toronto, they have a community of disabled testers that you can work with. They're amazing. And they'll test prototypes, pages, product demos, whatever you put in front of them, and they will test it with a variety of screen readers and voice navigation and magnification in Zoom.

[00:06:58] So they can really catch you on some biases, which is what happened for me. I was like, cool. I know the screen reader techniques work great. I was not thinking about low vision like magnification in Zoom. And I was not thinking about voice navigation. So it was really helpful for me to bring in these prototypes and get other perspectives that I was not considering, and it ended up really affecting my advice, which was kind of a combination of all of these techniques.

[00:07:27] So what I ended up landing on was move focus into the new content, so from the nav link you clicked on, move it into the new page somewhere. And I actually found moving it to something focusable and operable like a button, like a skip link maybe, something that's like a heading is not interactive.

[00:07:49] So I've learned maybe that would be more helpful, and then separately make a live region announcement so that the page change is announced. And so there's a whole research study, if you're curious, you can go read about it on the Getsby.js site. That's where I worked when I did this research.

[00:08:08] This has been referenced in almost all of the JavaScript frameworks. So I've seen it in Svelte. I've seen View talk about it. I mean React, it's funny though, they don't at me on GitHub, but I'll see the link pops up, hey, cool, they're referencing this in JavaScript libraries, so you might see it pop up a little bit.

[00:08:29] And that's neat because if people are hungry for this type of research and it was so awesome to do. That I think even aside from what the findings were for client-side routing, we could let it be an example of how you can engage with user testing with a group like Fable, cuz that was super cool.

[00:08:50] And if you wanna look at a demo, I do have one in the slides, a little routing demo of like, I guess we could look at it real quick. Let's see what I mean by client-side routing. So in this example, I have two routes. I click them, and my focus, I can move from the link to the main content area.

[00:09:14] And that's basically what I'm saying, whether you leave the focus where it was over here on the left, or do you move it to the new content. And so this uses a random third party router that I found, but there's plenty of routing libraries. Look for ones that give you hooks so that you can actually say where the focus should go.

[00:09:38] Cuz some of the challenges with libraries trying to solve that for us is that it's really hard to get it right for every use case. Like when you send focus, it can mess with scrolling. Sometimes it can mess with browser history. And so like React Router and Remix, they've been trying to find a solution for years and haven't quite landed on one.

[00:09:56] I think the pros I promise that we're hoping that the navigation API in Chrome will handle it at the browser level. But in the meantime, look for routers that will allow you to move focus to the right place or just use multi -page sites. So, real talk real quick.

[00:10:16] I did all this research. I love Javascript. I'm not a huge fan of client side routing, I have to be honest with you, and it's because a lot of the solutions are kind of half baked and we end up just marginalizing, that screen reader experience of being like, I don't know what happened.

[00:10:32] It's like hasn't been quite important enough to solve and it's hard to get it right. We've done all the experimentations of trying to move focus to the main content area for everyone that uses a router and people disable it. It doesn't work. So find a solution that works for you, client-side routing can be cool.

[00:10:53] You can actually be more, you can dictate more of where focus should go because you're crafting it, but we can't exactly mimic full page refreshes. That's when the browser refreshes and the screen reader really like, you can configure those to read the whole page summary. We just can't replace that functionality with client-side routing.

[00:11:14] So if you're choosing how to architect your site, at least put in your decision criteria about whether you could get away with multi-page. You can have that page have a lot of client rendering on it, but maybe you don't have a router. That's what the site I work on does.

[00:11:32] And it's kind of refreshing, I'll be honest. A lot less concerns. But we can always change that, we have client side routing. So these are the techniques you could look for, look at. And I think at the bare minimum, this first one of sending focus to the main heading and the new content, it wasn't the one I ended up recommending at the end of the research story, but I think it's it's better than just leaving Focus where it was.

[00:11:58] So you have some options. Any questions on client side routing?
>> I have one. I was scanning the article that you linked, that you wrote for Gatsby, and there's a sentence here that I'm curious about. It says, a back button would help to use browser history, and it was a limitation of the prototype.

[00:12:16] So does that mean that, because assistive technologies don't have hooks into the native browser, routing forward backward buttons, is that something that you'd lose out on?
>> I think you can hook into browser DOM APIs like the the navigator API. I'm pretty sure you can.
>> Is that considered a dark pattern cuz I use that a lot myself but is that less accessible, inherently, if you're using these technologies?

[00:12:40]
>> Not necessarily. I think, yeah, as I've read about, l seeing what the Remix team and React Router team is the same people. But seeing what they've tried, I've seen some comments about it, some things messing with history. I think you just have to test solutions, make sure they still work.

[00:12:57] But a lot of those DOM APIs should work fine. I think it's more like where you move focus and how the page change is announced, how is that communicated? Those are the things that kind of just get skipped. So I think those are the concerns that we have to look at and then try to keep browser history working.

[00:13:19] I've seen so many client routed sites that just don't even hook into browser history. It's like we gave up that feature, but I think you could add support back in. [LAUGH] But you could see this is like, you end up having to replace the stuff that you took away.