Skip to main content


A non-comprehensive guide to accessibility best practices when using Stacks.

All Stack Overflow product UIs must conform to the AA conformance level of the Web Content Accessibility Guidelines (WCAG) 2.2 with a few exceptions around color contrast documented below.

When high contrast mode is enabled, Stack Overflow product UIs must meet or exceed the Success Criterion 1.4.6 Contrast (Enhanced) of the Web Content Accessibility Guidelines (WCAG) 2.2 and should conform to the remaining AAA conformance level rules when reasonably achievable. This only applies to the subset of Stack Overflow products that provide high contrast modes. Note: not all Stack Overflow products are expected to support high contrast modes.

Stack Overflow product UIs MUST conform to a custom conformance level of the Accessible Perceptual Contrast Algorithm (APCA). This custom conformance level replaces the AA conformance level of the Web Content Accessibility Guidelines (WCAG) 2.2 for color contrast.

Stacks aims to equip you with an accessible color palette and has been tested against WCAG AA, WCAG AAA and the newer APCA color standards. Most of our color combinations meet WCAG AA and APCA levels defined below. We also offer high contrast mode which offers a greater level of contrast.

Contrast is the difference in luminance or color between any two elements. All visual readers require ample luminance contrast for fluent readability. Stack Overflow products must conform to a custom conformance level of the Accessible Perceptual Contrast Algorithm (APCA). Based on our custom conformance level, all text must have a Lightness contrast (Lc) value of 60, body copy must have a Lc value of 75, icons must have a Lc value of 45, and placeholder and disabled text must have a Lc of 30. These numbers will be negative when calculating for dark mode.

Use luminance contrast that meets our standards as defined above.
Use low luminance contrast that fail our standards.

Visual readers with color vision deficiency (CVD) have problems differentiating some hues and therefore these users need help discerning differences between items. This means that color (hue) should never be the sole means of communicating information and should always be paired with a non-color dependent indicator to accommodate all visual users.

Use an icon alongside color to convey meaning.
Use color alone to convey meaning.

Some people navigate through a website by using a keyboard or other device (instead of a mouse). A focus state should clearly let users know which item they’re on and is ready to interact with. Stack’s has taken a hybrid approach in using both the browser’s default styles (smaller interactive components like text links) and a custom focus ring.

Foundation for custom approach

Section titled Foundation for custom approach

The custom approach adds two different outline rings on the inside of the component. The outer ring color uses secondary-theme-400 theme-secondary-400 (matching the primary button color) and the inner ring color uses white white (matching the background).

The outer ring color will always display as the theme color even when applied to a muted or danger styled button. This ensures the focus ring maintains a 3:1 color contrast ratio for any adjacent colors (WCAG level AA) within any theme (assuming the secondary-theme color theme-secondary-400 already passes the 3:1 contrast ratio).

Both focus rings are always 2px thick. This allows the focus state to meet WCAG 2.4.13 Focus Appearance (AAA) standards for High Contrast mode. Whenever possible, the rings should be added to the inside of the component so we can better ensure that the rings don't get accidentally cut off by the surrounding layout (which helps us to meet WCAG 2.4.11 Focus Not Obscured AA). However, this does result in a padding reduction within the element, surrounding the text. When choosing to set the focus rings on the inside (inset), the component must have at least 4px of padding at the smallest size. This has been applied to buttons, button groups, navigation, pagination and topbar.

When the padding amount is not sufficient enough to support a double ring on the inside of the component, the rings are placed on the outside. The components included are tags, toggles, form elements (input fields, selects, radio/checkboxes…), block links and the editor.


Any component that already has an existing background color that fills the shape will maintain its original fill color.

For components that have an existing border around the component when not in focus, a background fill color is added in addition to the focus rings. This ensures there’s a strong enough visual difference between the non-focus and focus state, especially in the case of the .s-btn__outlined (which already displays a theme colored ring as default state). These patterns are maintained across all components for consistency.

page 2
page 2

Components without an existing fill or border will only display the double rings on focus. Since the inner ring matches the background color in most cases, this will visually appear like a single ring around the perimeter of the component.

The exceptions to this pattern are the Clear button variations. To avoid these buttons resembling s-btn__outlined when in focus, the same background fill layer is added as well. All buttons display a background fill layer when in focus. Clear, Outline and Filled styles will all look the same when in focus. The fill color was chosen to match the existing Filled style. For Muted variations, since Muted Filled has been deprecated, the fill color is pulled from the text color used on Outline before being reversed to white.

Some focusable elements and Stacks components currently do not include custom focus styling. These elements will instead render the browser-default focus indicators.

All Stack Overflow products must conform to the WCAG 2.2 SC 1.4.10: Reflow. This requires that our product UIs support viewports as small as 320px x 256px without requiring the user scrolling in multiple dimensions (unless an element requires it for usage or meaning). Very few users will ever use a viewport this small, but it's important to support it so users can zoom in up to 400% and still have a usable experience. At 400% zoom, a 320x256 viewport translates to 1280x1024, which is a common resolution for many users. Supporting this small viewport size ensures that users with low vision can still use our products effectively.

There are some exceptions to this rule. Some elements such as tables and videos may require horizontal scrolling on small viewports. In these cases, it's acceptable to require scrolling in two dimensions. See the WCAG 2.2 documentation on Reflow for detailed guidance.

Deploys by Netlify