Question

Styling SVG Paths Loaded with img in CSS

cssimagesvg

Question

How can I change the fill color of an SVG path with CSS when the SVG is loaded using an <img> element?

<img src="logo.svg" alt="Logo" class="logo-img">
.logo-img path {
  fill: #000;
}

The logo.svg file has a native fill color of white (#fff). I expected this CSS to change its paths to black, but it does not work. Why does this happen, and what is the correct way to style the SVG?

Short Answer

You will learn why CSS selectors cannot reach <path> elements inside an SVG loaded through <img>, and when to use inline SVG, currentColor, SVG-specific styles, or an image filter instead.

Concept

An SVG can be used in several ways on a web page. The way you embed it determines whether your page's CSS can style its internal elements.

When you write:

<img src="logo.svg" alt="Logo">

The browser treats logo.svg as an external image document. Your HTML page can style the <img> element itself—its width, height, border, and similar properties—but the SVG's internal <path>, <circle>, and <rect> elements are not part of your page's DOM.

Therefore, this selector cannot match anything:

.logo-img path {
  fill: #000;
}

It means “find a path inside an element with the logo-img class.” But an <img> element has no child elements in the HTML document. The SVG file is loaded separately.

To style SVG shapes from your page CSS, the usual solution is to put the SVG markup directly in the HTML as an inline SVG. Then its <path> elements are real DOM elements that CSS can select.

This matters because SVGs are often used as icons, logos, status indicators, and controls whose colors need to react to themes, hover states, or component styles.

Mental Model

Think of an <img> element as a framed photograph. You can resize the frame or add a border around it, but you cannot use your page's CSS to repaint an object inside the photograph.

An inline <svg> is more like a drawing placed directly on your page. Its individual shapes—such as <path> elements—are available for CSS to select and recolor.

Take Quiz

Syntax and Examples

With an external SVG image, you can style the image box, but not the paths inside it:

<img src="logo.svg" alt="Logo" class="logo-img">
.logo-img {
  width: 48px;
  height: 48px;
}

/* Does not work: there is no path in the HTML DOM below img. */
.logo-img path {
  fill: #000;
}

To style the path, use inline SVG instead:

<svg class="logo-icon" viewBox="0 0 24 24" role="img" aria-label="Logo">
  <path d="M4 4h16v16H4z"></path>
</svg>
.logo-icon {
  width: 48px;
  height: 48px;
}

.logo-icon path {
  fill: #000;
}

A flexible icon pattern is to use currentColor in the SVG. currentColor means “use the element's CSS color value.”

<svg class="logo-icon" viewBox="0 0 24 24" aria-hidden="true">
  <path fill="currentColor" d="M4 4h16v16H4z"></path>
</svg>
.logo-icon {
  color: #000;
}

.logo-icon:hover {
  color: #2563eb;
}

The path changes because its fill follows the SVG element's color.

Step by Step Execution

Consider this inline SVG:

<svg class="status-icon" viewBox="0 0 20 20" aria-hidden="true">
  <circle cx="10" cy="10" r="8" fill="currentColor"></circle>
</svg>
.status-icon {
  color: seagreen;
  width: 20px;
  height: 20px;
}

Execution sequence:

  1. The browser parses the <svg> and its <circle> as elements in the page DOM.
  2. The .status-icon rule matches the <svg> and sets its color to seagreen.
  3. The circle has fill="currentColor".
  4. currentColor resolves to the inherited color value: seagreen.
  5. The browser draws the circle in seagreen.

If the same SVG were loaded with <img src="status-icon.svg">, a selector from the parent page could style the <img> box, but it could not select the circle within the SVG file.

Real World Use Cases

  • Theme-aware icons: Use currentColor so navigation icons automatically match light or dark text.
  • Buttons: Change an inline SVG icon color when a button is hovered, focused, disabled, or selected.
  • Status indicators: Show success, warning, and error colors with the same SVG shape.
  • Brand assets: Keep a fixed multicolor company logo as an <img> when it does not need page-controlled styling.
  • Generated UI components: Render inline SVG markup in a component when the application needs to control fill, stroke, size, or animation.
Take Quiz

Real Codebase Usage

In production code, developers usually choose one of these patterns based on the icon's needs:

Inline SVG with currentColor

This is common for single-color UI icons.

<button class="delete-button" type="button">
  <svg class="button-icon" viewBox="0 0 24 24" aria-hidden="true">
    <path fill="currentColor" d="M7 4h10l1 2h3v2H3V6h3zm1 6h8v10H8z"></path>
  </svg>
  Delete
</button>
.delete-button {
  color: #b91c1c;
}

.delete-button:hover {
  color: #7f1d1d;
}

CSS classes for multiple SVG parts

For an illustration or icon with several independently styled pieces, add classes directly to the SVG elements.

<svg class="chart-icon" viewBox="0 0 24 24" aria-hidden="true">
  <path class="chart-icon__bar" d="M3 12h4v9H3z"></path>
  <path class="chart-icon__bar" d="M10 7h4v14h-4z"></path>
  <path class="chart-icon__bar" d="M17 3h4v18h-4z"></path>
</svg>
.chart-icon__bar {
  fill: #2563eb;
}

Keep fixed assets as <img>

Use <img> for static logos and illustrations that should remain self-contained. It has simple semantics through alt text and keeps the page markup smaller.

For reusable application icons, teams often create an icon component that consistently sets viewBox, accessibility attributes, size, and currentColor behavior.

Common Mistakes

Assuming <img> contains SVG child elements

This does not work:

.logo-img path {
  fill: #000;
}

<img> is a replaced element, not a container for the SVG DOM. Use inline SVG if you need to target path.

Forgetting that an SVG has a hard-coded fill

If an inline SVG path contains fill="#fff", it may override a less specific stylesheet rule depending on the CSS rules involved. Prefer a deliberate style rule or use currentColor for colorable icons.

<!-- Flexible for theming -->
<path fill="currentColor" d="..."></path>

Styling color without using currentColor

Setting color does not automatically change SVG fills.

.icon {
  color: black;
}

For this to affect the drawing, the SVG needs fill="currentColor", stroke="currentColor", or a CSS rule such as .icon path { fill: currentColor; }.

Using fill when the icon is drawn with stroke

Some SVGs are outlines rather than solid shapes.

<path stroke="currentColor" fill="none" d="M4 12h16"></path>

Change stroke, not fill, for this type of icon.

Removing useful accessibility text

If an SVG communicates meaning, give it an accessible name, such as role="img" with aria-label, or provide visible text. If it is only decorative next to text, use aria-hidden="true".

Comparisons

Embedding methodCan page CSS target internal paths?Best use case
<img src="icon.svg">NoStatic logos and images with alt text
Inline <svg>...</svg>YesUI icons, hover states, theming, and animation
CSS background-image: url(icon.svg)NoDecorative backgrounds
SVG file with its own internal CSSOnly within that SVG fileSelf-contained SVG artwork
SVG propertyUse it for
fillSolid interiors of shapes
strokeLines and outlines
colorA source value for currentColor
currentColorMaking fill or stroke follow CSS text color
Take Quiz

Cheat Sheet

<!-- External SVG: CSS cannot select its internal path -->
<img src="icon.svg" alt="Settings">
<!-- Inline SVG: CSS can select its path -->
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
  <path fill="currentColor" d="..."></path>
</svg>
.icon {
  width: 1.5rem;
  height: 1.5rem;
  color: #111827;
}

.icon:hover {
  color: #2563eb;
}

/* Alternative to fill="currentColor" */
.icon path {
  fill: currentColor;
}
  • <img> can be resized and positioned, but its SVG internals cannot be selected by page CSS.
  • Use inline SVG when individual shapes must be styled.
  • Use fill for filled icons and stroke for outline icons.
  • Use currentColor to connect an SVG's color to CSS color.
  • Include a viewBox so inline SVG scales correctly.

FAQ

Why does .logo-img path not work?

The SVG loaded by <img> is an external image document. Its <path> is not a child element in your HTML page, so the selector cannot match it.

Can I change an external SVG color using only CSS?

Not by directly selecting its paths from the parent page. You can use a CSS filter for limited recoloring, but inline SVG is the reliable choice when exact styling is needed.

Should I use fill or color for SVG icons?

Use fill to paint a filled shape. Use color together with fill="currentColor" or stroke="currentColor" when you want the icon to follow its CSS text color.

What if my SVG is an outline icon?

Use stroke instead of fill, provided the SVG path is drawn with a stroke.

Can an SVG file contain its own styles?

Yes. A standalone SVG can include style rules or attributes that apply within that SVG file. Those rules are separate from the CSS in the HTML page that uses it as an <img>.

Is inline SVG accessible?

Yes, when used appropriately. Decorative icons should usually have aria-hidden="true". Meaningful SVGs need an accessible name, such as an aria-label.

Is <img> still useful for SVG files?

Yes. It is a good choice for static, self-contained logos and illustrations, especially when you need alt text and do not need to style internal shapes.

Take Quiz

Mini Project

Description

Build a small set of themeable inline status icons. The project demonstrates why inline SVG is appropriate when an application needs the same icon structure to display different colors for success, warning, and error states.

Goal

Create three status icons whose SVG colors are controlled entirely by CSS.

Requirements

  1. Use inline SVG markup rather than img elements.
  2. Create success, warning, and error icon variants.
  3. Use currentColor for each icon path.
  4. Set the variant colors with CSS classes.
  5. Add a hover color change to one variant.
Take Quiz

Keep learning

Related questions

View more