Handling icons in dark mode
Search intent: Scenario
Dark mode is not a matter of inverting colours. Pure black fills vanish outright, 1px strokes look thinner on dark surfaces, and colour icons can glare. The robust approach is to drive icon colour from theme variables rather than maintaining two unrelated sets of assets.
Contents
- Preferred: currentColor plus theme variables
- What about external img references
- Be careful with filter: invert
- Contrast and stroke width on dark surfaces
- Three ways to implement theme switching
Preferred: currentColor plus theme variables
Set fill / stroke to currentColor in inline SVG and change only the parent color when the theme switches; use CSS variables when you need several colour steps. Light, dark and high-contrast modes then share one file, with no risk of two sets drifting out of sync.
:root { --icon: #3e7c46; --icon-muted: #7d8c7f }
@media (prefers-color-scheme: dark) {
:root { --icon: #9ad0a4; --icon-muted: #6f8574 }
}
.icon { color: var(--icon) } /* SVG 内用 currentColor */What about external img references
External SVGs do not inherit page styles. Three routes: switch to inline; use a CSS mask where colour comes from background-color; or ship light and dark files and swap them under prefers-color-scheme. The third is the most obvious, but the two sets must be kept in sync.
Be careful with filter: invert
One line of filter: invert(1) does turn a black icon white, but colour icons and greyscale illustrations become strange hues and semi-transparent areas distort. It is only appropriate for pure monochrome icons, and ideally paired with hue-rotate to correct brand colours. Long-lived projects should still move to the variable approach.
- Pure monochrome line icons: invert is an acceptable stopgap
- Colour, duotone or illustration: prepare a dark variant
- Never invert a whole page, or your images flip too
Contrast and stroke width on dark surfaces
Icons carry information and still have to be legible: do not push secondary icons too dark, and do not rely on brightness alone to distinguish states. A 1.5px stroke looks thinner on dark, so consider raising stroke-width to 1.75 or 2 in dark mode and confirming on a real device.
Three ways to implement theme switching
The first is pure CSS media queries following the system setting — no script, simplest, and the user cannot override it on the site. The second is a data-theme attribute with your own toggle — most controllable, and what most products use. The third combines them: follow the system by default, persist a manual choice once made. All three impose the same requirement on icons: colour must not be hard-coded in the SVG. And remember to switch borders, dividers and disabled states at the same time; changing only icon colour makes the interface look half-converted.
- Follow the system: @media (prefers-color-scheme: dark)
- In-site toggle: data-theme plus CSS variables
- Hybrid: follow system by default, manual choice takes precedence
- Switch disabled states, dividers and borders together
FAQ
Related assets · 12 assets