DEV Community

Cover image for 10 tips for building accessible (rich) text editors
Julian Krispel-Samsel
Julian Krispel-Samsel

Posted on

10 tips for building accessible (rich) text editors

If you're building an app that features a rich text editor - you should make it as accessible as possible for screen-readers.

It's really not as hard as it sounds, so here's list of 10 recommendations for building accessible rich text editors. Although most points will be applicable to any kind of library you use, some of them are specific to react.js.

1. Test with an actual screen reader

If you have never used a screen reader, try one out on your app or any app with that has a rich text editor. I'd consider this blog-post a success even if you don't come back to finish reading it.

  • On OSX you already have one built in to your operating system: VoiceOver.
  • For Windows users there's nvda (free) which is also the most widely used.
  • Another popular screen reader is JAWS (not free).

All of the below recommendations become more obvious if you put yourself into your users shoes.

2. Avoid keyboard traps

Overriding default keyboard behaviour to implement features such as hotkeys or indenting text via tab is a common pattern seen in web-based rich-text editors and IDEs.

However, screen-reader users rely entirely on the keyboard to navigate your app, their browser and operating system. It is frustrating and hard to overcome if default keyboard functionality is prevented by an application. If you are implementing such features, check they don't collide with hotkeys that are already in use for the browsers or operating systems.

3. All interactive elements must be reachable via tab and/or arrow keys

Most rich text editing applications make use of menus and toolbars, dynamically positioned or fixed in place.

To ensure that elements are reachable via keyboard they need to be focusable. DOM elements such as button, input, select or textarea are focusable by default. If you're using an element that isn't considered interactive (such as a div) you are required to add a tabindex and a role attribute so that the screen reader knows how to interact with the element.

Consider how much work it is for a keyboard-only user (the mouse is mostly useless for a user with sight-issues) to navigate to these UI elements. This will depend on the position of the element in the DOM and how many other interactive elements are in between.

If you're building an editor with a floating toolbar (such as medium - which is completely inaccessible via tab keys btw) pay close attention to how a keyboard-only user can navigate to and from these buttons and toolbar components.

For complex usecases (if you have submenus or button groups) you should consider programmatically moving focus, more info on this here

4. Use alt text for your images and make them configurable

If you're rendering images in your editor, it is recommended you use an alt attribute to represent what the image contains to a screen reader.

However, for user submitted content it is too difficult to generate meaningful alt text automatically, that's why you should consider making the alt attribute configurable by the user. Here is what it looks like on

Alt text for images on

5. Label your icon buttons

Most rich text editors make use of common icons for text formatting and layout.

Google docs tool bar

These icons don't have textual meaning on their own, hence we need to tell the screen reader what they are by assigning the aria-label attribute like so:

<button aria-label="Bold" onClick={makeTextBold}>
Enter fullscreen mode Exit fullscreen mode

If you're not using the semantic button element, you need to assign the tabindex attribute (to make it tabbable) as well as the button role (to tell the screen reader that this is a button), see below:

Enter fullscreen mode Exit fullscreen mode

6. Use a linter with a11y support

To make it easier to stay on top of your apps accessibility, a linter can go a long way.

For react users, the a11y-jsx eslint plugin will make you aware of what attributes you're missing to make your web-app accessible. I cannot overstate how valuable this is especially for teams.

I recommend running your linter automatically (either as part of your CI or with a git hook).

7. Use an accessible component library

Using established component libraries will give you a leg-up on reaching a good accessibility baseline. Reach.ui, material ui and chakra are all react libraries that have decent accessibility defaults.

8. Think twice about whether you need collaborative editing

If your rich text editor has collaborative editing the content of a users document can change at the same time as you're editing it. The screen-reader needs to be notified that these updates occur, however these notifications must not be too noisy or distracting which can be a difficult balancing act.

Although there are no out of the box solutions for this, a good reference is googles "Live Edit's" feature, providing a list of edits made by other users.

Features such as this can be notoriously expensive to implement, test and maintain. My recommendation: Think twice about whether you actually need collaboration as part of your product before adding it to your roadmap.

9. Use a title attribute for iframes

Embedding content via iframes is a staple for rich text editors these days. To make this accessible for screen readers you should use the title attribute to describe what the iframe contains.

10. Always use the textbox role

Most frameworks (draft.js, slate.js and prosemirror as well as others) render this by default, but it's always good to double check this!

Any rich text editor using the contentEditable attribute (which is pretty much every rich text editor) needs to use the "textbox" role, to tell the screen-reader that it will respond to input and editing commands.

Thanks for reading, this article was originally posted on my website, for more content like this have a look and feel free to reach out on twitter too.

Top comments (0)