Making a feedback widget work in high-contrast mode

In forced-colors mode the browser replaces most colors with the user's chosen palette and drops box shadows and background images. Give the button a border, use system color keywords, and draw focus with outline so the button and its focus ring stay visible in high-contrast themes.

By 路 Published 路 Last updated

What does forced-colors mode change on a page?

High-contrast mode, which Windows calls contrast themes, tells the browser to replace the page's colors with a small palette chosen by the visitor. The browser ignores most of your color values, removes background images, and drops box shadows. Text becomes one color, controls get the palette's button colors, and links and focus use the palette's highlight color. A button that relies on a colored background and a soft shadow can vanish completely.

Pages can detect this with the forced-colors media feature, which reports active when the mode is on. Use that query to add the details the browser would otherwise remove, such as a border on a button or an outline on focus.

Why does focus disappear in forced colors?

Many sites draw focus with a box shadow, because it looks softer than an outline. In forced-colors mode the browser drops the shadow, and the focus ring disappears. A keyboard user then cannot see which control is active, which makes the panel unusable.

Use outline for focus rings. Outlines survive forced-colors mode, and they can be given a width and an offset that stay visible on any background. Keep outline on :focus-visible, so mouse users are not shown a ring after every click.

Which system colors should you use in CSS?

System color keywords follow the visitor's palette, so they stay correct in every contrast theme. The keywords you will use most often are ButtonText for the text on a button, ButtonFace for its background, Canvas and CanvasText for the page, Highlight for selections and active states, HighlightText for text on a highlight, and GrayText for disabled text.

Element Normal color Forced-colors value
Button background Your accent color ButtonFace
Button text White ButtonText
Button border None ButtonText, 2px
Focus ring Accent outline Highlight
Muted helper text Gray GrayText

Use system colors inside the forced-colors query only. Outside it, keep your brand colors, since they matter to visitors using the normal palette.

How do you write the forced-colors media query?

Write the normal styles first, then add the overrides for forced colors. Start with a border on every button, because a border is the one detail a contrast theme cannot remove, then use the system keywords:

.feedback-trigger {
  background: #1d4ed8;
  color: #ffffff;
  border: 2px solid transparent;
  border-radius: 8px;
  padding: 10px 16px;
}

.feedback-trigger:focus-visible {
  outline: 3px solid #1d4ed8;
  outline-offset: 2px;
}

@media (forced-colors: active) {
  .feedback-trigger {
    background: ButtonFace;
    color: ButtonText;
    border-color: ButtonText;
  }

  .feedback-trigger:focus-visible {
    outline-color: Highlight;
  }
}

The transparent border in the normal styles becomes a visible border in forced colors, because the browser replaces the color. Avoid forced-color-adjust: none unless you need a color that the browser would otherwise replace, such as a chart value that carries meaning, because turning the adjustment off ignores the visitor's choice.

Which accent colors survive contrast modes?

Your accent color matters in the normal palette, but it disappears in forced colors. That is why the border and the focus ring carry the design in that mode. In the normal palette, check the contrast between your accent and the white text on the button, with the contrast guidance from how to make a feedback widget accessible. In forced colors, check that the border has enough contrast against the page's background, because the palette you cannot choose decides it.

Icons need the same care. An SVG icon drawn with a fill or a stroke can disappear when the browser replaces that color, so set the stroke or fill to currentColor, which takes the text color and survives the palette change. An icon that carries meaning on its own, such as a warning sign next to an error, should also have a text label, so that the meaning survives even if the icon does not.

A few habits make the difference. Use a border on every control, not only the button. Keep the text and the border in the same palette group, so they remain distinct. Avoid placing meaning in color alone, such as a red error with no icon or text. An error message should say what is wrong, whatever the palette.

How do you test a feedback button in contrast themes?

Test on real contrast themes, not only in a simulator, because the palettes differ.

  1. On Windows, open Settings, go to Accessibility, then Contrast themes, and choose a theme. Load the page, then press Tab until the feedback button has focus, and check that the border and the focus ring are visible.
  2. Open the panel with Enter, type a short message and check the type buttons, the rating control and the send button.
  3. Press Escape, check that focus returns to the trigger, and confirm the trigger is still visible.
  4. In Chrome or Edge DevTools, open the Rendering panel, find the option to emulate a CSS media feature, and set forced-colors to active. Repeat the checks.
  5. Zoom the page in to at least double its normal size, repeat the checks, and confirm the panel still fits the screen.

Checking the Escuta Produto widget under contrast modes

Run the steps above on your own install, using the accent color you actually ship. Check the floating button, the panel's type buttons, the stars and the send button in each palette. If a control loses its boundary or its focus ring, write down the element and the theme, then add the fix to your own CSS where the control is yours, such as a trigger button with data-trigger set to none. The widget's options are listed in the widget docs. For the rest of the keyboard and screen reader checks that go with the same panel, see keyboard shortcut to open feedback.

Frequently asked questions

What is forced-colors mode?

A high-contrast setting in which the browser replaces most page colors with a palette chosen by the visitor, and drops box shadows and background images. Pages can detect it with the forced-colors media feature and add borders and outlines to stay usable.

Why does my feedback button disappear in high-contrast mode?

The button probably relies on a background color or a box shadow, and both are removed or replaced in forced-colors mode. Add a visible border that uses a system color, and check that the text uses the system text color.

How do I keep focus visible in a high-contrast theme?

Draw the focus ring with the outline property rather than a box shadow, because outlines survive forced-colors mode. Use focus-visible so mouse users are not shown a ring after each click, and set the outline color to a system keyword such as Highlight.