SVG Lab

7 August 2026 · Usman Bashir

How to Change SVG Colors (fill, stroke, currentColor, and the img tag problem)

How to change an SVG's colors with fill, stroke, currentColor, and CSS, plus why colors in an img tag won't respond to CSS at all.

To change an SVG's color, edit its fill and stroke attributes (or the CSS that sets them) rather than treating the file like a raster image. Which method works depends on where the color lives: as an inline attribute, in a <style> block, or in the parent page's CSS, and those three don't always agree on which one wins.

This trips people up because SVG carries color in more places than a PNG or JPG ever could. A single icon might have color baked into six different paths, referenced through CSS, or locked out entirely because of how it's embedded on the page. Here's what's actually going on.

fill vs stroke

Every shape in an SVG can have two separate colors:

<circle cx="50" cy="50" r="40" fill="#3366ff" stroke="#000000" stroke-width="2" />

A shape can have one, both, or neither set (an unset fill defaults to black, an unset stroke defaults to none). If you change a color and nothing happens, check you're editing the one that's actually visible. Icon fonts converted to SVG are usually pure fill with no stroke at all, which is the most common reason a "stroke" edit does nothing.

Three places a color can live, and which one wins

A color can be set three ways, and they follow normal CSS specificity rules:

  1. Presentation attribute, directly on the element: <path fill="red" />
  2. Inline style attribute: <path style="fill: red;" />
  3. A <style> block or external stylesheet: path { fill: red; }

The cascade order is: style attribute beats stylesheet rules, which beat presentation attributes. So if you edit the fill="red" attribute on a path but a <style> block elsewhere in the file also targets that path, the stylesheet wins and your attribute edit is silently ignored. This is the single most common "I changed the color and nothing happened" bug. If an edit isn't taking, search the whole file for a <style> tag or a class on the element before assuming the tool is broken.

currentColor: the one worth knowing

currentColor is a special CSS/SVG keyword that means "whatever the current text color is." Set an SVG's fill to it:

<path fill="currentColor" d="..." />

and the icon inherits color from its container, the same way text does:

.icon { color: #ff0000; }
<span class="icon">
  <svg fill="currentColor" ...>...</svg>
</span>

Change color on the wrapper and the icon updates with it, no SVG edit required. This is why most icon libraries ship their SVGs with fill="currentColor" instead of a hardcoded hex value: one icon file, any color, controlled entirely from CSS. If you're building your own icon set and want it to behave the same way, currentColor is the mechanism, not a special editor feature.

Why colors in <img src="icon.svg"> can't be changed with CSS

This is the one that catches people off guard. If you reference an SVG through an <img> tag:

<img src="icon.svg" />

the browser treats it as an opaque image, the same as a PNG. None of the SVG's internal structure is exposed to the page's CSS. You cannot target fill or path from outside, and currentColor won't resolve to anything because there's no inheritance path into an external image document. filter: invert() or similar CSS filters can shift the color somewhat, but that's a blunt approximation, not a real color change.

Three actual workarounds:

  1. Inline the SVG directly into the HTML instead of referencing it with src. Once its markup is part of the page, it's a normal DOM element and CSS applies normally.
  2. Use it as a CSS mask instead of an image source:
    .icon {
      background-color: currentColor;
      mask: url(icon.svg) center / contain no-repeat;
      -webkit-mask: url(icon.svg) center / contain no-repeat;
    }
    The SVG's shape becomes a mask, and the visible color comes from background-color, which you can change freely.
  3. Use an SVG sprite with <use>, and set the fill on the <use> element or its wrapper. This only works if the original paths don't already have a hardcoded fill fighting you.

If you just need one specific color on one specific icon, the simplest fix is usually to open the file and edit it directly rather than reaching for a CSS workaround at all.

Multi-path SVGs: one color change usually isn't enough

Icons and illustrations are rarely a single shape. A two-tone logo might be five separate <path> elements, each with its own fill. Changing one path's color and expecting the whole graphic to update is the second most common source of confusion after the cascade issue above. If you want the graphic to move as a single color, either:

For anything with more than two or three paths, editing by hand in a text editor gets tedious fast, since you're hunting through raw markup for every fill= occurrence rather than seeing the shapes.

CSS variables inside SVG

SVG's <style> blocks accept normal CSS, which means custom properties work too:

<svg>
  <style>
    :root { --icon-color: #3366ff; }
    .body-fill { fill: var(--icon-color); }
  </style>
  <path class="body-fill" d="..." />
</svg>

Set once, referenced by every shape that shares it. If the SVG is inlined in the page (not loaded via <img>), you can even override the variable from the page's own CSS, giving you a single hook for a multi-part graphic's whole color scheme without duplicating the value across paths.

Doing this without hand-editing markup

All of the above is normal SVG and CSS, no tool required, and worth knowing regardless of what you use day to day. But hunting through raw fill= attributes across a dozen paths gets old, and it's easy to miss one nested inside a <style> block that's overriding your edit. SVG Lab is a free browser SVG editor I built that does fill and stroke color editing visually along with path and node editing, so you can see and click the shape you're changing instead of grepping markup for it. It's at svglab.app, no install, and free to use.

Open the SVG editor Back to the blog