Using currentColor for icons in light and dark themes
Hard-coded icon colors work until the surrounding interface changes. A dark icon may disappear in a dark header, while a bright icon may become unreadable on a pale button. For simple interface artwork, inheriting the component's text color can make the styling relationship much easier to maintain.
Understand the color relationship
In inline SVG, currentColor lets a stroke or fill use the element's computed CSS color. That means a button can define one color for its label and icon. Keep fill set to none for an outline drawing unless the paths are intended to be filled. Changing every attribute to currentColor indiscriminately can fill open shapes or remove meaningful visual distinctions in a multicolor illustration.
Use it where inheritance is wanted
A menu arrow, search symbol, or small status decoration is often a good candidate. A brand logo or carefully composed multicolor illustration may not be. Decide which parts of an asset should follow the interface and which should keep their own color. If a duotone design uses a separate fill layer, review that layer explicitly rather than assuming that a single inherited color will preserve the intended effect.
Account for the embedding method
Inline SVG participates in the page's style tree. An SVG loaded as an ordinary image is a separate resource, so setting color on the parent will not automatically recolor its internal paths. This distinction explains many reports that currentColor is broken. Inspect how the asset is embedded before changing the file. If the integration only accepts images, export appropriately colored assets or choose a different supported rendering approach.
Define states, not just themes
A component may have default, hover, focus, disabled, and error states within each theme. Define color tokens for those states and let the icon follow when that is appropriate. Check colored buttons separately from plain text links. A single gray chosen for a light background may not work everywhere. Avoid making disabled icons so faint that users cannot recognize the action they are currently unable to perform.
Try a real component
Export a simple icon with dynamic color enabled, then place it inside the actual button. Change the button's CSS color and confirm that both text and icon update. Next test the dark theme and keyboard focus. If a path remains black, inspect its local fill or stroke declaration. A hard-coded attribute or inline style can be responsible. Keep the final rule close to the component rather than applying a broad rule to every SVG on the page.
Implementation example
.icon-action { color: #0f766e; }
.icon-action:hover { color: #115e59; }
.dark .icon-action { color: #99f6e4; }
/* Inside an inline outline SVG: fill="none" stroke="currentColor" */Follow the color through a button
Imagine a text button whose normal color is dark green and whose hover color is white on a darker background. An inline SVG path using currentColor can follow those text-color changes without a separate icon hover rule. Trace the value from the button to the SVG and then to its paths. A nested element with an explicit color declaration can interrupt the inheritance you expected. Likewise, a hard-coded stroke or fill on the path can take precedence over the treatment you meant to apply. Inspect the computed styles in the receiving page rather than repeatedly exporting the file in different colors. Keep the component's color decisions close to its text and background states. This makes the hover behavior easier to understand and reduces the chance that the label changes while the symbol stays behind in an unreadable color.
Handle mixed-color artwork deliberately
Some icons contain a primary stroke and a secondary translucent fill. You may want both to follow one theme color with different opacity, or you may want the secondary region to use a separate token. Decide this explicitly instead of replacing every color value in a complex file. Brand marks, warning illustrations, and status badges can require fixed or independently controlled colors. A global rule such as applying currentColor to every descendant path can flatten those distinctions and remove important visual information. Review the SVG's structure and choose the elements that should inherit. If you need two independently adjustable colors, document that contract in the component or asset specification. Test each combination against its actual background, including hover and selected states. Dark mode is a coordinated relationship between foregrounds, backgrounds, and emphasis, not simply a request to make all icons white.
Debug a theme mismatch methodically
First identify how the asset is embedded: inline markup, a component, an image element, or another mechanism. Next inspect the element that is supposed to supply the color and confirm its computed value. Then inspect the SVG's own color, fill, and stroke declarations. Check whether a more specific rule, inline style, or hard-coded attribute explains the mismatch. Change one cause at a time and test the ordinary state before moving to hover or focus. If an external image is expected to inherit page text color, reconsider the integration method rather than adding increasingly broad CSS selectors. Finally, compare a light surface, a dark surface, and a colored button surface. Keep an example page containing these contexts so future theme changes can be reviewed quickly. A small, representative component gallery is more reliable than checking one icon in isolation and assuming every placement will behave identically.
Continue reading: Understanding viewBox, empty space, and cropped SVG icons
Try it with an icon
Browse a collection, customize an icon in the studio, and review the result in your actual project.
Browse icon collections →