Editor toolbars are dense, pale and small. A grey icon on a white background, with the active state shown only by a slightly darker grey, looks tidy in a design review and is hard to read at a glance. The pressed state of Bold is the thing a writer most needs to see, and it is often the least visible element on the screen. Contrast is a checkable property, and a toolbar should pass the same check as the body text.
What the standard asks for
WCAG asks for at least 4.5 to 1 contrast between text and its background, and 3 to 1 for large text and for the parts of a user interface a person needs in order to understand a control. Icons that carry meaning, such as the bold “B” or a list glyph, fall in the second group. A focus ring also needs 3 to 1 against the surface beside it. Check each state separately: normal, hover, pressed, focused and disabled.
Show the pressed state with more than colour
A pressed button that changes only its background from one light grey to a slightly darker one fails for many readers. Add a second cue that does not depend on colour: a stronger border, an inset outline, or a change in the icon itself. The toolbar should still show which formatting is active when the screen is in greyscale.
.toolbar-button[aria-pressed="true"] {
background: var(--surface-pressed);
color: var(--text-strong);
box-shadow: inset 0 0 0 1px var(--text-strong); /* a shape cue, not only a colour cue */
}
.toolbar-button:focus-visible {
outline: 2px solid var(--focus-ring);
outline-offset: 2px;
}The sample uses the aria-pressed attribute as the source of truth, so the visual state and the announced state match. A pressed style driven by a class name added by hand can drift out of step with the screen reader, and the writer hears one state while seeing another.
Check dark mode as its own design
Colours that pass on a white toolbar often fail on a dark one, because the same grey is used for text and background in both themes. Set the colour tokens for each theme separately and run the contrast check on each pair. Do not derive dark colours by inverting light ones, since the result is often muddy and below the threshold.
Disabled controls are exempt, but still need to be readable
The standard does not require contrast for an inactive control, and many designs make disabled buttons very pale on purpose. A pale Undo button tells the writer that undo is unavailable, which is useful. A pale button they cannot tell apart from its neighbour is not. Keep the disabled state visibly different, and make the reason available as a tooltip or a short description.
A short test list
- Run a contrast check on the toolbar icons in light and dark themes, in normal and pressed states.
- Switch the screen to greyscale and confirm the pressed Bold button is still distinguishable.
- Tab through the toolbar and confirm the focus ring is visible against both the toolbar and the page.
- Turn on Windows high-contrast mode and confirm the icons and active states remain visible.
- Check that a disabled button is different from an enabled one without relying on colour alone.
RichTextEditor is a perpetual-licence JavaScript editor — one purchase, self-hosted, no metered editor loads. Download the evaluation or see how it compares.