June 10, 2026
A Browser Testing Checklist for Dark Mode, Reduced Motion, and High-Contrast UI Settings
A practical browser testing checklist for dark mode, reduced motion, high-contrast mode, prefers-color-scheme, and other accessibility settings, with Playwright examples and QA guidance.
Dark mode, reduced motion, and high-contrast settings are not edge cases anymore. They are part of the normal range of browser and OS preferences that real users depend on, and they often expose UI problems that standard functional tests will never catch. A component can pass every click-path check and still become unreadable, motion-sick, or visually broken as soon as the operating system switches themes or the browser reports a different accessibility preference.
If you work on frontend systems, this is where a focused browser testing checklist for dark mode becomes useful. The goal is not just to confirm that the page still renders, but to verify that color, spacing, animation behavior, focus states, and contrast all remain usable when users change their environment.
The tricky part is that these issues usually appear at the boundaries between design tokens, CSS, browser rendering, and component state. That means the defects are often subtle, but still severe for the person using the interface.
This checklist is written for frontend engineers, QA teams, and accessibility testers who want a practical way to validate UI behavior across OS-level and browser-level preferences. It focuses on appearance and interaction issues, and it assumes you want a repeatable process, not a one-off manual audit.
Why these settings deserve dedicated browser coverage
Most teams already test responsive breakpoints, supported browsers, and a few core user flows. The gap is that accessibility settings change how the browser should render the same interface. That means the application might be logically correct while still failing visually or interactively.
The main settings to cover are:
prefers-color-scheme, which controls light and dark color schemes,- reduced motion preferences, usually exposed via
prefers-reduced-motion, - high-contrast or forced-colors modes, often through browser or OS accessibility settings,
- browser zoom and text scaling, which can magnify the same classes of defects.
These preferences affect more than colors. They can change whether icons are readable, whether borders disappear, whether transitions make content inaccessible, and whether focus indicators remain visible against new backgrounds.
The relevant standard family is the WCAG guidelines, especially the parts that affect contrast, keyboard accessibility, animation, and perception of information. You do not need to memorize every criterion to test effectively, but you do need a checklist that maps preferences to likely failure modes.
What to include in your browser testing checklist
Use the checklist below as a baseline for every major UI surface, then expand it for complex components such as dashboards, editors, data grids, and media-heavy pages.
1. Verify theme inheritance at the root level
Start with the document and application shell, not individual widgets.
Check that:
- the root element responds to system theme changes,
- body and app shell colors swap correctly,
- theme-specific tokens are applied consistently,
- no component hardcodes light-only or dark-only colors,
- background layers still create enough separation between panels, headers, and overlays.
A common issue is partial theming, where core layout surfaces adapt but nested cards, dropdowns, or tooltips still use stale colors. That creates a patchwork UI that looks intentional only in one mode.
If your system uses CSS variables, inspect whether dark mode values cover every semantic token, not just the obvious ones like background and text. Secondary labels, divider lines, input borders, placeholder text, disabled states, and shadows often get missed.
2. Confirm text contrast in every state
Color contrast is not just about the default text color on the default background. Test all states that matter:
- normal body text,
- muted text and metadata,
- disabled controls,
- placeholder text,
- links in rest, hover, active, and visited states,
- error messages and success messages,
- text over colored badges, chips, tags, and hero banners.
In dark mode, many designs fail because the palette is lifted from light mode and simply inverted. The result is often low-contrast gray-on-gray text or accent colors that are too saturated on dark surfaces.
A good heuristic, if you need to squint to read a label in either theme, the palette is probably too close to the edge.
3. Test focus visibility against every background
Keyboard focus is one of the easiest things to lose when themes change. A focus ring that works on a white background can disappear on charcoal, and a subtle outline can be swallowed by high-contrast overlays.
Check:
- focus ring color and thickness,
- whether the ring is clipped by overflow containers,
- whether interactive elements have visible focus in dark mode,
- whether custom components preserve
:focus-visiblebehavior, - whether the active item in menus, tabs, and sidebars remains obvious.
If you use a custom token for focus color, test that it passes contrast against both light and dark backgrounds. If focus is expressed with shadows instead of outlines, verify that the shadow remains visible in forced-colors environments, where browser rendering can be simplified.
4. Validate icon, illustration, and SVG behavior
Icons often depend on currentColor, strokes, or mixed fills. They can look correct in one theme and vanish in another.
Look for:
- monochrome icons that inherit text color correctly,
- icons with embedded hardcoded fills that do not adapt,
- SVGs that are too thin in high-contrast mode,
- line icons that disappear on dark surfaces,
- icons used as the only indicator for actions or status.
If an icon communicates state, do not rely on color alone. Make sure text labels, tooltips, or ARIA labels convey meaning, especially when contrast settings alter the palette.
5. Check form controls in all accessibility settings
Forms are where many theme bugs become user-facing blockers. Inputs, dropdowns, radios, checkboxes, selects, switches, and textareas need a special pass.
Confirm that:
- borders remain visible on dark backgrounds,
- placeholder text is distinguishable from typed text,
- disabled controls still look disabled without becoming unreadable,
- custom checkboxes and radios keep a visible checked state,
- validation colors are distinct and not red-on-maroon or green-on-green,
- autofill styles do not break the theme.
Also verify cursor and caret visibility. A bright caret can be obvious in one theme and almost invisible in another, especially on tinted fields.
6. Exercise hover, active, pressed, and selected states
State changes are easy to overlook because tests usually click and move on. In accessibility-driven themes, the state palette itself often changes.
Check:
- button hover and pressed state contrast,
- selected tabs and list items,
- active nav links,
- chip selection and deselection,
- dropdown highlighted options,
- drag handles and reorder affordances.
Do not assume the selected state can be represented by color alone. If users run high-contrast mode, the browser may override colors or simplify effects, so you need secondary indicators such as borders, underline, checkmarks, or text weight.
7. Validate motion reduction behavior, not just animation presence
Reduced motion testing is not only about disabling a fancy animation. It is about making sure motion-dependent interactions still work when transitions are removed or shortened.
Test for:
- carousel autoplay behavior,
- modal open and close transitions,
- toast animation timing,
- collapsible panels,
- accordions,
- drawer and sheet transitions,
- loading spinners and skeleton shimmer effects.
The main question is whether the interface remains understandable when motion is reduced. A menu that slides from the side may still be fine if it opens instantly. A complex sequence that depends on animation timing, however, can become confusing if the intermediate states are skipped.
For CSS, the preference usually maps to prefers-reduced-motion. A minimal implementation often looks like this:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
That pattern is not perfect for every app, but it is a useful signal that your product respects the preference. The key is to audit individual interactions after the global rule is in place.
8. Check forced colors and high-contrast mode behavior
High contrast mode testing is different from ordinary dark mode testing. In forced-colors environments, the browser or OS may override your palette entirely, which means custom gradients, subtle shadows, and decorative fills may not survive as designed.
Test:
- whether text remains readable when the palette is overridden,
- whether buttons and links are still distinguishable,
- whether borders and outlines remain visible,
- whether important state information survives without color,
- whether custom controls have usable system color mappings.
A CSS snippet can help you reason about the mode, but the actual test should be visual and interactive:
@media (forced-colors: active) {
.button {
forced-color-adjust: none;
border: 1px solid ButtonText;
background: ButtonFace;
color: ButtonText;
}
}
Use forced-color-adjust carefully. Opting out of the browser’s forced-color handling can be appropriate for a few components, but it can also backfire if you do not restyle every relevant state.
9. Inspect overlays, menus, and modal stacks
Transient UI surfaces are often where accessibility settings reveal layout bugs.
Look at:
- modal backdrops,
- popovers,
- context menus,
- tooltips,
- combobox suggestion lists,
- nested dialogs.
These components can fail in dark mode if the backdrop and panel colors are too close. They can fail in high contrast mode if the border disappears, the shadow is suppressed, or the focus trap makes the active item hard to identify.
Also verify z-index stacking with theme-aware shadows. A shadow that creates depth in light mode can become visually meaningless in dark mode, so borders and spacing may need to do more work.
10. Recheck data-heavy surfaces
Tables, analytics dashboards, and dense list views are notorious for accessibility setting regressions because they pack many states into a small area.
Test:
- row striping or alternate row backgrounds,
- sticky headers,
- sort indicators,
- inline status badges,
- heatmap cells or severity chips,
- empty states and loading states.
When the palette changes, your table may lose the visual separation that keeps it scannable. Dense UIs should still have enough line height, row height, and contrast to avoid becoming a wall of text.
11. Verify links, visited states, and non-color affordances
Links need careful attention because theme changes often flatten the distinction between body text and hyperlink color.
Check that:
- links are still identifiable without relying only on blue,
- hover and focus states are distinct,
- visited styling is meaningful but not distracting,
- inline links in dark mode remain visible on body copy,
- destructive and non-destructive actions are not encoded only by color.
If your design system supports subtle underlines, those often survive theme changes better than color-only cues. In high contrast environments, underlines can become more useful than custom link hues.
12. Confirm spacing and layout stability after theme switches
Theme transitions can alter font rendering, border thickness, icon visibility, and component size. That means a layout that fits in light mode can wrap, overflow, or shift when preferences change.
Watch for:
- labels wrapping onto multiple lines,
- truncated text becoming ambiguous,
- buttons losing alignment in toolbars,
- icons nudging text out of alignment,
- headers changing height and pushing content below the fold.
These are not just cosmetic problems. A theme toggle that changes layout can also change what is visible on the screen at any given scroll position, which is especially problematic in forms and workflows with validation.
A practical manual test sequence
If you only have time for a short pass, use this order:
- Load the page in default light mode.
- Switch to dark mode at the OS or browser level, then refresh and observe the entire page.
- Navigate with keyboard only and confirm focus visibility.
- Trigger key overlays, dropdowns, and dialogs.
- Enable reduced motion and repeat the same interactions.
- Enable high contrast or forced colors and recheck the most important flows.
- Compare key screens side by side with a known-good baseline.
This order helps you catch regressions early, because the root shell and shared components usually fail before the deepest interaction paths do.
When a setting changes, do not only ask whether the page still works. Ask whether the UI still communicates state clearly enough for the user to trust it.
Playwright checks for accessibility preferences
For teams already using browser automation, Playwright is a practical way to codify some of this checklist. It is especially helpful for smoke coverage across multiple browsers, because it can emulate several media features and confirm that the page responds to them.
Here is a small example that checks color scheme and reduced motion behavior at a high level:
import { test, expect } from '@playwright/test';
test('theme and motion preferences', async ({ page }) => {
await page.emulateMedia({ colorScheme: 'dark', reducedMotion: 'reduce' });
await page.goto('https://example.com');
await expect(page.locator(‘body’)).toHaveCSS(‘color-scheme’, ‘dark’); await expect(page.getByRole(‘button’, { name: ‘Open menu’ })).toBeVisible(); });
Use this as a starting point, not as the full test. The hardest part is not the emulation itself, it is deciding what to assert. In most cases, assertions should be centered on visible state, not implementation details.
For Selenium or Cypress teams, the same principle applies. Emulate the preference if your runner supports it, then validate real user-visible behavior such as focus rings, contrast, and panel visibility.
What to automate versus what to inspect manually
Not every accessibility preference issue is a good candidate for strict assertions. Some are better handled with visual regression, and some still need human inspection.
Good candidates for automation
- page renders in dark mode without broken layout,
- buttons, links, and form controls are visible,
- dialogs and menus open correctly,
- focus is present and detectable,
- motion-related preferences do not break flow,
- high-contrast mode still shows key boundaries.
Better for visual or exploratory review
- whether color pairs feel balanced,
- whether subtle gray text is still comfortable to read,
- whether a themed illustration clashes with the background,
- whether motion feels too abrupt or too slow,
- whether forced-colors fallback is acceptable for a complex widget.
This is where visual regression tools can add value. A product like Endtest, an agentic AI test automation platform,’s Visual AI can help repeated checks catch meaningful rendering changes across browsers and devices, especially when you want a practical execution layer for recurring baseline comparisons. If your team also wants built-in accessibility scanning, Endtest’s Accessibility Testing option can complement the visual pass with WCAG-oriented checks. The useful part is not the brand name, it is the combination of repeatability and coverage.
Common failure patterns to watch for
Here are the regressions that show up again and again in this area:
- dark mode toggles only the background, not the component surfaces,
- icons use hardcoded fills and disappear on darker backgrounds,
- disabled text becomes too dim to read,
- focus rings are present but blend into the theme,
- transitions are disabled globally, but content still relies on timing,
- high contrast mode removes borders that were carrying structural meaning,
- shadow-only elevation makes panels indistinguishable,
- charts and status colors lose meaning without labels or patterns,
- custom form controls are not mapped to system colors.
Many of these defects come from layering one-off fixes on top of a design system that was never built around semantic tokens. If that sounds familiar, the checklist can also help you identify where the token model needs work.
How to build this into CI without making it noisy
Accessibility preference checks are easy to over-automate. If every theme combination is tested on every commit, your suite can become slow and flaky. A better pattern is to separate quick smoke coverage from deeper visual coverage.
A pragmatic setup looks like this:
- run a small set of preference-aware smoke checks on every pull request,
- run broader dark mode and reduced motion visual checks nightly,
- reserve forced-colors and high-contrast coverage for critical paths and release branches,
- compare baselines only on screens that are intentionally stable.
If your team uses continuous integration, this kind of split keeps the signal high without turning every visual change into a release blocker. For a general reference on the concept, see continuous integration and test automation.
A minimal GitHub Actions job might look like this:
name: ui-accessibility-smoke
on: pull_request:
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npm ci - run: npm run test:ui
The details depend on your runner, but the structure should be familiar, keep the fast tests on the PR path and the heavier visual matrix elsewhere.
A concise checklist you can reuse
Use this as a repeatable review template for each major screen:
- Root theme switches correctly in light and dark modes.
- Text contrast remains readable in all states.
- Focus indicators are visible and not clipped.
- Icons still communicate meaning without relying on color only.
- Forms remain usable, including placeholders, validation, and disabled states.
- Hover, active, and selected states remain distinct.
- Motion reduction does not break interactions.
- Forced colors or high contrast mode preserves structure and affordances.
- Overlays, menus, and dialogs remain legible and scannable.
- Data-dense layouts remain readable and aligned.
- Links and calls to action are still recognizable.
- No theme switch causes layout shift that hides content or controls.
If a screen fails in one preference mode, treat it as a real defect, not a cosmetic tweak. For users relying on these settings, the difference between usable and unusable is often very small.
Final take
A browser testing checklist for dark mode, reduced motion, and high-contrast UI settings is really a checklist for UI resilience. It asks whether your design system survives outside the default happy path, and whether the interface still communicates clearly when the environment changes underneath it.
The best teams do not treat these preferences as a separate accessibility project. They bake them into browser testing, visual regression, and component review from the start. That means checking theme tokens, focus states, motion preferences, and forced-colors behavior as part of normal release work, not as a last-minute polish pass.
If you already have Playwright or Selenium coverage, add preference-aware smoke checks to your existing suite. If you need a broader visual pass across browsers, pair those checks with a repeatable visual baseline workflow. The payoff is simple, fewer surprises when real users turn on the settings they depend on every day.