Skip to main content
Back to Blog

How to Change SVG Icon Color with CSS: currentColor, Variables & Dark Mode

Learn how to control SVG icon colors using CSS. Fix hardcoded fills, use currentColor for inheritance, apply CSS custom properties for theming, and support dark mode — with practical code examples.

6 min read
svg
css
color
dark-mode

Why SVG Colors Can Be Tricky

SVG icons exported from design tools — or generated by AI — often come with hardcoded fill attributes directly on elements:

<svg viewBox="0 0 24 24">
  <path fill="#1a1a1a" d="M12 2L2 7l10 5 10-5-10-5z"/>
  <path fill="#1a1a1a" d="M2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>

When you try to change the color with CSS, nothing happens:

svg {
  color: blue; /* doesn't work */
  fill: blue;  /* still doesn't work */
}

This is the most common SVG frustration developers encounter. The reason: inline fill attributes have higher specificity than CSS rules. The browser sees the inline fill="#1a1a1a" and ignores your stylesheet entirely.

There are three ways to solve this, each suited to different situations.

Solution 1: Remove Inline Fills and Use CSS

The simplest fix is to remove the hardcoded fill attributes from the SVG markup:

<svg viewBox="0 0 24 24">
  <path d="M12 2L2 7l10 5 10-5-10-5z"/>
  <path d="M2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>

Now CSS works as expected:

svg {
  fill: blue;
}

Without an inline fill, SVG elements default to fill="black". Your CSS rule overrides this default with no specificity conflict.

When to use this: When you have full control over the SVG source and only need one color.

Solution 2: Use currentColor for Inherited Color

currentColor is the most powerful technique for making SVG icons flexible. It tells the SVG to use the text color value from its parent element:

<svg viewBox="0 0 24 24" fill="currentColor">
  <path d="M12 2L2 7l10 5 10-5-10-5z"/>
  <path d="M2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>

Now the icon color is controlled by the CSS color property:

.nav-link {
  color: #333;
}

.nav-link:hover {
  color: #0066cc;
}

.nav-link svg {
  fill: currentColor; /* inherits color from .nav-link */
}

The icon automatically matches the text color and responds to state changes like :hover and :focus.

currentColor with Stroke Icons

For outline-style icons that use stroke instead of fill, apply currentColor to the stroke:

<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
  <circle cx="12" cy="12" r="10"/>
  <path d="M12 8v4l3 3"/>
</svg>
.icon {
  color: #666;
}

This is the pattern used by popular icon libraries like Lucide and Heroicons. Both set stroke="currentColor" so icons automatically match surrounding text.

Why currentColor Works

currentColor is a CSS keyword that resolves to the computed value of the color property on the same element. When used as an SVG attribute value, it creates a bridge between CSS color inheritance and SVG rendering. The icon becomes part of the document's color flow rather than an isolated graphic with its own colors.

When to use this: When icons should match adjacent text color. This is the recommended default for most icon use cases.

Solution 3: CSS Custom Properties for Multi-Theme Support

For more complex theming — where you need different colors for different contexts — CSS custom properties (variables) give you precise control:

:root {
  --icon-primary: #1a1a1a;
  --icon-secondary: #666666;
  --icon-accent: #0066cc;
}
<svg viewBox="0 0 24 24">
  <path fill="var(--icon-primary)" d="M12 2L2 7l10 5 10-5-10-5z"/>
  <path fill="var(--icon-secondary)" d="M2 17l10 5 10-5M2 12l10 5 10-5"/>
</svg>

Now you can change multiple icon colors at once by updating the variables:

.dark-section {
  --icon-primary: #ffffff;
  --icon-secondary: #aaaaaa;
  --icon-accent: #66aaff;
}

CSS Variables in SVG Attributes vs. Stylesheets

CSS custom properties work in both SVG attributes and stylesheets, but with a difference:

In attributes (inline):

<path fill="var(--icon-color)"/>

In stylesheets (CSS):

path {
  fill: var(--icon-color);
}

Both work in modern browsers. The attribute approach is convenient when each element needs a different variable. The stylesheet approach is better when all paths share the same color.

When to use this: When you need different color themes across sections, or when icons have multiple colors that need independent control.

Dark Mode Support

Using prefers-color-scheme

The prefers-color-scheme media query lets icons automatically adapt to the user's system preference:

:root {
  --icon-color: #1a1a1a;
}

@media (prefers-color-scheme: dark) {
  :root {
    --icon-color: #e0e0e0;
  }
}

svg {
  fill: var(--icon-color);
}

Class-Based Dark Mode (Tailwind CSS)

If your project uses a class-based dark mode toggle (common with Tailwind CSS), use the .dark class:

:root {
  --icon-color: #1a1a1a;
}

.dark {
  --icon-color: #e0e0e0;
}

With Tailwind's utility classes, you can apply dark mode inline:

<svg class="fill-gray-800 dark:fill-gray-200" viewBox="0 0 24 24">
  <path d="M12 2L2 7l10 5 10-5-10-5z"/>
</svg>

currentColor + Dark Mode — The Best Combo

The most maintainable approach combines currentColor with dark mode text color:

body {
  color: #1a1a1a;
}

@media (prefers-color-scheme: dark) {
  body {
    color: #e0e0e0;
  }
}
<svg fill="currentColor" viewBox="0 0 24 24">
  <path d="M12 2L2 7l10 5 10-5-10-5z"/>
</svg>

With this pattern, icons follow the text color into dark mode without any icon-specific CSS. No variables, no extra rules — just currentColor inheriting from the document's color scheme.

Fixing AI-Generated SVG Icons

AI-generated SVG icons (including those from our AI Icon Generator) typically output hardcoded fill values. Here's how to make them theme-ready:

Step 1: Generate your icon

Step 2: Remove hardcoded fills or replace them with currentColor

Before:

<svg viewBox="0 0 24 24">
  <path fill="#000000" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10..."/>
</svg>

After:

<svg viewBox="0 0 24 24" fill="currentColor">
  <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10..."/>
</svg>

Step 3: Optionally, run through our SVG Optimizer to clean up other redundant attributes

This three-step workflow — generate, update color handling, optimize — produces production-ready icons that work in any color context.

Quick Reference

TechniqueUse CaseBrowser Support
Remove inline fill + CSSSingle-color icons, simple stylingAll browsers
currentColorIcons that match text colorAll browsers
CSS custom propertiesMulti-theme, multi-color iconsAll modern browsers
prefers-color-schemeAutomatic dark modeAll modern browsers
Tailwind dark: utilitiesClass-based dark modeAll modern browsers

Related Tools

  • AI Icon Generator — Generate SVG icons from text descriptions, then apply these color techniques
  • SVG Viewer — Preview your color changes in real time
  • SVG Optimizer — Clean up redundant fill attributes and other bloat after editing