Question

How to Change SVG Color in CSS: fill, img, image, and Inline SVG

csssvgcolors

Question

I want to change the color of an SVG using CSS, but it is not working. I tried applying a fill style, yet the image always stays black.

Here is my code:

<style>
.change-my-color {
  fill: green;
}
</style>

<svg>
  <image
    class="change-my-color"
    xlink:href="https://svgur.com/i/AFM.svg"
    width="96"
    height="96"
    src="ppngfallback.png"
  />
</svg>

Why does the SVG remain black, and how can I correctly change its color?

Short Answer

By the end of this page, you will understand why fill does not affect an externally loaded SVG inside an <image> element, and how to correctly style SVG colors using inline SVG, SVG paths, and currentColor. You will also learn common patterns developers use when they need recolorable icons in real projects.

Concept

In SVG, color is often controlled with properties such as fill and stroke.

  • fill changes the inside color of shapes.
  • stroke changes the outline color.

However, where the SVG comes from matters.

In your example, the SVG file is loaded through an <image> element:

<svg>
  <image xlink:href="icon.svg" />
</svg>

This behaves more like placing an image file inside SVG, not like exposing the internal SVG shapes to CSS. Your CSS can style the <image> element itself, but it cannot reach inside the external SVG file and change the path, circle, or other shape colors.

That is why fill: green; does not recolor the external SVG content.

To change SVG color with CSS, the most common solution is to use inline SVG:

<svg viewBox="0 0 24 24" class="icon">
  <path d="..." />
</svg>

Now CSS can target the actual SVG shapes:

.icon {
  fill: green;
}

This matters in real programming because SVG icons are everywhere:

  • navigation menus
  • buttons
  • status badges
  • charts
  • logos
  • dark mode themes

If you want flexible styling, hover effects, theme colors, or dynamic states, inline SVG is usually the best choice.

Mental Model

Think of an external SVG file inside <image> like a photo in a picture frame.

  • You can move the frame.
  • You can resize the frame.
  • But you cannot repaint the shapes inside the photo with normal CSS.

Inline SVG is like having the actual drawing instructions on the page.

  • You can target the shapes directly.
  • You can change their color.
  • You can animate them.
  • You can respond to hover, active, or theme changes.

So the key idea is:

  • External SVG in <image> or <img> = mostly not directly colorable with fill
  • Inline SVG = directly colorable with CSS
Take Quiz

Syntax and Examples

1. Styling inline SVG with fill

<svg class="icon" viewBox="0 0 24 24" width="96" height="96">
  <circle cx="12" cy="12" r="10" />
</svg>
.icon {
  fill: green;
}

This works because the SVG markup is directly in the HTML.

2. Styling a specific shape inside SVG

<svg viewBox="0 0 24 24" width="96" height="96">
  <circle class="icon-shape" cx="12" cy="12" r="10" />
</svg>
.icon-shape {
  fill: green;
}

This is useful when an SVG contains multiple parts with different colors.

3. Using currentColor

A common pattern is to make the SVG follow the text color of its parent.

<button class="icon-button">
  <svg class="icon" viewBox="0 0 24 24" width="24" height="24">
    <path d="M5 12h14" stroke="currentColor" stroke-width="2" />
  </svg>
  Save
</button>
.icon-button {
  color: blue;
}

Because the SVG uses currentColor, the icon becomes blue automatically.

4. What does not work for external SVG in <image>

<svg>
  <image class="change-my-color" href="icon.svg" width="96" height="96" />
</svg>
.change-my-color {
  fill: green;
}

This does not recolor the shapes inside icon.svg.

5. Correct approach: paste the SVG inline

If the external file contains something like this:

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <path d="M12 2L2 22h20z" />
</svg>

Put it directly in your HTML:

<svg class="warning-icon" viewBox="0 0 24 24" width="96" height="96">
  <path d="M12 2L2 22h20z" />
</svg>
.warning-icon {
  fill: orange;
}

Now the color can change.

Step by Step Execution

Consider this inline SVG example:

<svg class="icon" viewBox="0 0 24 24" width="50" height="50">
  <rect x="4" y="4" width="16" height="16" />
</svg>
.icon {
  fill: green;
}

Here is what happens step by step:

  1. The browser reads the HTML and creates an <svg> element.
  2. Inside that SVG, it finds a <rect> shape.
  3. The browser reads the CSS rule for .icon.
  4. The <svg> element has class icon, so the rule matches.
  5. The fill: green property is applied to the SVG.
  6. The <rect> uses that fill value, so the rectangle is drawn in green.

Now compare that with this external image version:

<svg>
  <image class="icon" href="icon.svg" width="50" height="50" />
</svg>
.icon {
  fill: green;
}

What happens here:

  1. The browser reads the outer <svg>.
  2. It finds an <image> element that references an external file.
  3. The CSS rule matches the <image> element.
  4. But the actual drawing inside icon.svg stays separate.
  5. fill: green does not reach the shapes inside that external file.
  6. The image displays using its own internal colors, often black if the source SVG is black.

That is the core reason your original code does not work.

Real World Use Cases

Recolorable UI icons

Applications often need icons that change color based on state:

  • gray when disabled
  • blue when active
  • red for errors
  • green for success

Inline SVG makes this easy.

Dark mode support

A site may switch from light mode to dark mode. Icons should follow the theme color automatically.

Using currentColor lets icons inherit color from surrounding text or components.

Hover and interaction states

Buttons and links often change icon color on hover:

.button {
  color: #444;
}

.button:hover {
  color: #0a84ff;
}

If the SVG uses currentColor, the icon changes too.

Status indicators

Dashboards often use SVG for:

  • warning triangles
  • success checkmarks
  • error symbols
  • loading shapes

These need dynamic coloring based on data.

Data visualizations

Charts and diagrams built with SVG often rely on fill and stroke to show categories, trends, or thresholds.

Take Quiz

Real Codebase Usage

In real projects, developers usually choose one of these patterns:

Inline SVG for icons

This is the most common option when icons need to be styled.

<svg class="icon icon-success" viewBox="0 0 24 24">
  <path d="M20 6L9 17l-5-5" fill="none" stroke="currentColor" stroke-width="2" />
</svg>
.icon-success {
  color: green;
}

currentColor for theme-friendly icons

This pattern avoids hardcoding colors in the SVG.

.nav-link {
  color: #555;
}

.nav-link.active {
  color: #1d4ed8;
}

The icon follows automatically if it uses fill="currentColor" or stroke="currentColor".

Component-based apps

In React, Vue, or similar frameworks, developers often store icons as components so they can pass color, size, or class names.

Guarding against hardcoded SVG colors

Many downloaded SVG files contain fixed values like:

<path fill="#000000" d="..." />

This blocks flexible styling. Developers often replace it with:

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

or remove the inline fill and style it in CSS.

Validation and cleanup

Before using SVGs in a codebase, developers often:

  • remove unnecessary metadata
  • simplify paths
  • replace fixed fills
  • make sizing consistent with viewBox

This makes icons easier to maintain.

Common Mistakes

1. Trying to style an external SVG loaded with <img> or <image>

Broken example:

<img class="icon" src="icon.svg" alt="icon">
.icon {
  fill: red;
}

Why it fails:

  • fill does not recolor the internal shapes of the external file.

How to avoid it:

  • use inline SVG when you need CSS-based color changes

2. The SVG file has hardcoded fill values

Broken example:

<svg class="icon" viewBox="0 0 24 24">
  <path fill="#000000" d="M12 2L2 22h20z" />
</svg>
.icon {
  fill: green;
}

Why it may fail:

  • the path already has its own fill value

Fix:

<svg class="icon" viewBox="0 0 24 24">
  <path d="M12 2L2 22h20z" />
</svg>

or:

<path fill="currentColor" d="M12 2L2 22h20z" />

3. Using fill when the shape is drawn with stroke

Broken example:

<svg class="icon" viewBox="0 0 24 24">
  <path d="M5 12h14" stroke="black" stroke-width="2" fill="none" />
</svg>
.icon {
  fill: green;
}

Why it fails:

  • the visible line uses stroke, not fill

Fix:

.icon {
  stroke: green;
}

or use stroke="currentColor".

4. Forgetting viewBox

Without viewBox, scaling can behave strangely.

Better example:

<svg class="icon" viewBox="0 0 24 24" width="24" height="24">
  <circle cx="12" cy="12" r="10" />
</svg>

5. Using outdated xlink:href unnecessarily

Older SVG examples use xlink:href. Modern SVG usually supports href.

Example:

<image href="icon.svg" width="96" height="96" />

If you maintain older code, you may still see xlink:href, but for new code href is usually simpler.

Comparisons

ApproachCan CSS change SVG color?Best forNotes
Inline SVGYesIcons, interactive graphics, themed UIMost flexible option
<img src="icon.svg">Usually noSimple display-only imagesEasy to use, not good for recoloring
<svg><image href="icon.svg"></image></svg>Usually noEmbedding external image content inside SVGDoes not expose inner shapes to CSS
SVG with currentColorYesButtons, nav items, text-linked iconsGreat for theme and state changes
Hardcoded fill="#000" inside SVGLimitedFixed-color artworkHarder to reuse

fill vs stroke

PropertyWhat it colorsCommon use
fillInside of shapesSolid icons, circles, rectangles, paths
strokeOutline of shapesLine icons, borders, checkmarks, arrows

currentColor vs fixed color

OptionBenefitDrawback
currentColorInherits from parent text color, easy themingRequires understanding inheritance
Fixed color like fill="red"Simple for one-off graphicsHarder to reuse across themes and states
Take Quiz

Cheat Sheet

Quick rules

  • Use inline SVG if you want to style color with CSS.
  • fill colors the inside of a shape.
  • stroke colors the outline.
  • External SVGs loaded via <img> or <image> are usually not recolorable with CSS fill.
  • currentColor makes an SVG follow the element's text color.

Common patterns

Inline SVG with fill:

<svg class="icon" viewBox="0 0 24 24">
  <path d="..." />
</svg>
.icon {
  fill: green;
}

Inline SVG with currentColor:

<svg class="icon" viewBox="0 0 24 24">
  <path d="..." fill="currentColor" />
</svg>
.icon-wrapper {
  color: purple;
}

Stroke-based icon:

<svg class="icon" viewBox="0 0 24 24">
  <path d="M5 12h14" stroke="currentColor" stroke-width="2" fill="none" />
</svg>

If color is not changing, check:

  • Is the SVG inline?
  • Is the visible part using fill or stroke?
  • Does the path have a hardcoded fill or stroke?
  • Are you targeting the correct element?
  • Does the SVG have a proper viewBox?

Best practice

For reusable UI icons:

  • keep SVG inline or as a component
  • use fill="currentColor" or stroke="currentColor"
  • control color through the parent with CSS

FAQ

Why does fill not work on my SVG image?

Because your SVG is being loaded as an external image. CSS cannot usually style the internal shapes of that file.

Can I change the color of an SVG loaded with <img>?

Not directly with normal fill styling. For easy recoloring, use inline SVG instead.

What is the difference between fill and stroke in SVG?

fill colors the inside of shapes, while stroke colors the outline.

What does currentColor do in SVG?

It tells the SVG to use the current text color of its parent or element, which is very useful for theming.

Why is my inline SVG still black?

The SVG may have hardcoded fill="#000" or stroke="#000" attributes that override your CSS.

Should I use href or xlink:href for SVG images?

For modern code, href is generally preferred. Older examples may still use xlink:href.

What is the best way to build color-changing icons?

Use inline SVG with fill="currentColor" or stroke="currentColor", then control color with CSS.

Take Quiz

Mini Project

Description

Build a small status icon panel that displays three SVG icons: success, warning, and error. The goal is to practice using inline SVG and currentColor so each icon can be recolored with simple CSS classes. This mirrors how many real interfaces style icons for alerts, forms, dashboards, and notifications.

Goal

Create a set of inline SVG icons whose colors are controlled entirely through CSS classes.

Requirements

  • Display three status items: success, warning, and error.
  • Each item must include an inline SVG icon and a text label.
  • Use currentColor so the icon color follows the parent element.
  • Give each status item a different CSS color.
  • Keep the SVG markup valid and scalable with viewBox.
Take Quiz

Keep learning

Related questions

View more