How Chromium Implements Forced Colors Mode for Windows
This article explains the technical architecture behind Chromium’s implementation of Forced Colors Mode, a feature designed to seamlessly integrate Windows High Contrast themes into web content. It covers how the browser detects operating system accessibility settings, translates native Windows color palettes into standardized CSS system colors, and uses the Blink rendering engine to strip and override web author styles. Finally, it examines how Chromium maintains text readability over complex backgrounds and gives developers control over specific elements using modern CSS properties.
Operating System Detection
Chromium bridges the gap between the Windows operating system and web
content through its native theme layer
(ui::NativeThemeWin). The browser actively monitors Windows
system events, specifically listening for the
WM_THEMECHANGED and WM_SYSCOLORCHANGE
messages.
Using the Windows API function SystemParametersInfo with
the SPI_GETHIGHCONTRAST flag, Chromium detects the exact
moment a user enables a High Contrast theme. Once detected, the browser
updates its internal state and notifies the Blink rendering engine to
enable Forced Colors Mode and trigger the
@media (forced-colors: active) media query.
Mapping Windows Colors to CSS System Colors
When High Contrast is active, Chromium retrieves the specific color
palette defined by the user in Windows settings using the
GetSysColor API. To adhere to W3C web standards and
maintain user privacy, Chromium does not expose raw Windows APIs
directly to the web. Instead, it maps these OS-level colors to
standardized CSS System Colors:
- Windows
COLOR_WINDOWmaps to CSSCanvas(backgrounds). - Windows
COLOR_WINDOWTEXTmaps to CSSCanvasText(body text). - Windows
COLOR_HOTLIGHTmaps to CSSLinkText(hyperlinks). - Windows
COLOR_GRAYTEXTmaps to CSSGrayText(disabled elements). - Windows
COLOR_HIGHLIGHTandCOLOR_HIGHLIGHTTEXTmap to CSSHighlightandHighlightText(selected text). - Windows
COLOR_BTNTEXTandCOLOR_BTNFACEmap to CSSButtonTextandButtonFace(UI controls).
This mapping ensures that semantic HTML elements automatically receive the exact colors the user configured in their operating system.
Style Resolution and Overrides in Blink
Once the color map is established, the Blink rendering engine alters
how it resolves CSS. Rather than simply injecting a high-specificity
stylesheet, Blink enforces Forced Colors Mode directly within its
StyleResolver and ElementRuleCollector
components during the CSS cascade phase.
Chromium intercepts specific CSS properties defined by the website author and forces them to revert to the user agent's default values, which are dynamically bound to the CSS System Colors. The overridden properties include:
colorbackground-colorborder-coloroutline-colorcolumn-rule-colortext-decoration-colorwebkit-tap-highlight-colorfillandstroke(in specific User Agent contexts)
Additionally, to eliminate visual clutter that reduces contrast,
Chromium forces box-shadow and text-shadow to
none. It also removes author-defined
background-image properties on certain interactive elements
(like buttons and links) to ensure their boundaries and text remain
clearly visible.
The Text Backplate Mechanism
Because Forced Colors Mode does not strip
background-image from standard div or
body containers, text can still end up sitting on top of a
complex image, making it unreadable.
To solve this, Chromium implements a "backplate" in its painting
phase. As the layout tree is painted, Chromium identifies paragraphs and
clusters of text. It then draws a solid rectangle using the
Canvas system color directly behind the text nodes, sitting
on a layer between the text and any underlying images. This guarantees
strict adherence to the user's contrast requirements without deleting
informative background images from the webpage.
Handling Developer Opt-Outs
There are scenarios where forcing colors breaks the core
functionality of the content, such as color swatches on an e-commerce
site or syntax highlighting in a code editor. Chromium implements the
forced-color-adjust CSS property to handle these
exceptions.
During style calculation, if Blink encounters
forced-color-adjust: none on an element, it disables the
Forced Colors cascade overrides for that specific element and its
descendants, restoring the web author's original CSS. Chromium also
automatically applies
forced-color-adjust: preserve-parent-color to SVG elements
by default. This ensures that vector icons inherit the high-contrast
text color of their parent element without having their internal paths
and multi-colored fills completely washed out by global overrides.