# Make an SVG icon follow your text colour with currentColor

> One keyword removes the need for colour variants, dark mode icons and inline fill overrides. Here is how currentColor works and the three places it breaks.

URL: https://semanticicons.com/blog/svg-currentcolor-icons
Published: 2026-09-30
Updated: 2026-09-30

An icon set that ships colours is an icon set you will fight. Every use needs an override, every theme needs a variant, and every variant drifts.

The fix is one keyword.

```html
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  <path d="M4 20 L12 4 L20 20" />
</svg>
```

`currentColor` resolves to the computed CSS `color` of the element. Put the icon inside a button, and it takes the button's text colour. Change the theme, and it changes with it. No prop, no variant, no override.

## What it removes

| Without currentColor | With currentColor |
| --- | --- |
| A light and a dark version of every icon | One version |
| A `color` prop on the icon component | None |
| An inline `fill` at every use | None |
| A CSS rule per context | One rule on the parent |

For a 3000 icon set the first row alone is the difference between 3000 files and 6000.

## The rule that makes it work

`currentColor` only helps if nothing else in the file sets a colour. That means the icon file must hold **shapes only**, with no `fill`, `stroke`, `style` or `class` attributes of its own.

Our library stores each icon as its inner elements, and the renderer supplies the wrapper:

```html
<!-- stored -->
<rect x="2.5" y="2.5" width="19" height="19" rx="3.5"/>
<path d="M7 15.5 L11 8.5 L15 15.5"/>
```

The consequence is that a change to the contract is one edit. When we needed round joins across the whole set, it was one attribute in one renderer, not 3000 file edits.

## The three places it breaks

### A hard coded fill in the source

Icons exported from a drawing tool almost always carry `fill="#000000"` on every path. That wins over the parent colour, so the icon stays black in dark mode. Strip fills and strokes at import time, not by hand later.

### A multi colour icon

A flag, a logo or a colour coded status icon has colours that are part of its meaning. `currentColor` cannot express that. Keep those out of the monochrome set, and let them carry their own colours. Do not compromise the whole set for a handful of files.

If you need one accent inside an otherwise monochrome icon, a CSS custom property with a fallback works:

```html
<path stroke="currentColor" d="..."/>
<circle fill="var(--icon-accent, currentColor)" cx="18" cy="6" r="3"/>
```

### An `<img>` tag or a CSS background

An SVG loaded through `<img src="icon.svg">` or `background-image` is a separate document. It has no access to your page's CSS, so `currentColor` resolves to black.

This is the most common surprise. If you need `currentColor`, the SVG must be **inline in the DOM**: rendered by a component, or injected. A sprite referenced with `<use>` keeps it, because the sprite is in the same document.

| Delivery | currentColor works |
| --- | --- |
| Inline `<svg>` in the markup | Yes |
| `<use href="#id">` from an inline sprite | Yes |
| `<img src="icon.svg">` | No |
| CSS `background-image` | No |
| `mask-image` with `background-color` | Effectively, yes |

That last row is the workaround for CSS-only cases. Use the SVG as a mask and let the background colour show through.

## Dark mode, in one line

With `currentColor`, dark mode is whatever your text colour already does:

```css
:root { color: #13161b; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color: #e8eaee; }
}
```

The icons follow. There is nothing else to do, and no second set to keep in step. See [designing icons for dark mode](/blog/icons-in-dark-mode) for the cases where that is not quite enough.

## Questions people ask

### Does currentColor work in every browser?

Yes. It is part of SVG 1.1 and CSS Color 3, and it works everywhere including older browsers. It is one of the safest features in the platform.

### Can I use currentColor for fill and stroke together?

Yes. Set both if the icon mixes filled and stroked shapes. They resolve to the same colour, which is usually what a monochrome icon wants.

### How do I make one icon a different colour?

Set `color` on the icon or its parent, not `fill`. Because the icon reads `currentColor`, setting `color: red` on the wrapper turns the icon red without touching the SVG.

### What about opacity for a secondary detail?

Use `stroke-opacity` or `fill-opacity` rather than a lighter colour. Opacity keeps the icon correct on any background; a hard coded lighter grey does not.
