Go to homepage

← All articles Last edited:

SVG and CSS: a guide to styling and animating SVG elements

SVG icons can be easily customized using CSS when imported inline in an HTML document.

In this article, we'll show how to stylize SVGs in CSS and the advantages of using CSS compared to inline attributes.

SVG elements support a wide range of attributes that can be adjusted directly within the HTML to change their appearance. Consider the example below, where attributes like viewBox, width, height, fill, and d are defined inline within the <svg> and <path> elements:

<svg viewBox="0 0 18 18" width="18" height="18">
  <path fill="#f0a2a2" d="..." ></path>
</svg>

However, many of these attributes can also be customized using CSS. Attributes such as height and width can be modified just like any CSS property:

svg {
  height: 24px;
  width: 24px;
}

Given SVGs are vector files, adjusting their size through CSS doesn't compromise their quality. Using CSS classes for resizing provides a practical method for controlling SVG dimensions:

<style>
  .icon-sm {
    height: 24px;
    width: 24px;
  }

  .icon-md {
    height: 32px;
    width: 32px;
  }
</style>

<svg viewBox="0 0 18 18" class="icon-sm">
  <!-- ... -->
</svg>

This makes your icon system easier to maintain: updating your icon sizes is a matter of modifying one CSS class, rather than the height and width inline attributes of each of your icons.

If you want to read more about changing SVG sizes, check our article on resizing SVG icons.

Some SVG attributes are standard CSS properties (like height and width); some others are specific to SVG.

For example, to control the background color of an SVG, you can use the fill and the stroke attributes. Fill controls the SVG content's color, while the stroke changes the outline color (you can imagine it as the color of the SVG border).

svg {
  fill: #6C43E8;
  stroke: #6C43E8;
}

Below an example of SVG icons with only fill color (first row) and SVG icons with only a stroke color (second row):

SVG fill and stroke
SVG icons with fill (first row) and stroke (second row) - from the Nucleo UI library

Additionally, you can control the SVG color opacity using the fill-opacity and stroke-opacity attributes, as well as the outline width using the stroke-width attribute:

.icon {
  stroke-width: 2px;
  fill-opacity: 0.5;
  stroke-opacity: 0.5;
}

It's important to note that CSS styles will override inline SVG attributes. Consider the following example:

<svg class="icon" fill="red" viewBox="0 0 18 18"  xmlns="http://www.w3.org/2000/svg">
  <!-- svg content here -->
</svg>

<style>.icon {fill: yellow;}</style>

The SVG fill color will be yellow - CSS style values overwrite the inline fill attribute.

This precedence makes CSS an ideal solution for maintaining the style of inline SVG icons, with easy updates through CSS class modifications without altering the SVG code.

For the complete list of SVG attributes that can be manipulated with CSS, check out the following links:

There are several JavaScript libraries designed for animating SVG elements, like Lottie and Rive, among others.

However, CSS Animations and Transitions often provide all that's needed to craft animations without relying on additional JavaScript. SVG loaders are a great example.

Take a look at this SVG animation:

In this animation, the <svg> is rotated and scaled using a CSS Animation:

svg {
  transform-origin: 50% 50%;
  animation: nc-loop-dots-anim 1s infinite cubic-bezier(.645,.045,.355,1)
}

@keyframes nc-loop-dots-anim {
  0% {transform: scale(1)}
  50% {transform: scale(.7) rotate(90deg)}
  100% {transform: scale(1) rotate(180deg)}
}

There are cases when it's necessary to animate different elements within an SVG, such as with the following loader:

To achieve this loader effect, you can animate the clock hour and minute hands separately:

.nc-loop-clock-anim-icon-f > * {
  transform-origin: 50% 50%;
}

.nc-loop-clock-anim-icon-f > :nth-last-child(2) {
  /* this is the minutes hand */
  animation: nc-loop-clock-anim-m 0.5s infinite linear;
}
.nc-loop-clock-anim-icon-f > :nth-last-child(1) {
  /* this is the hours hand */
  animation: nc-loop-clock-anim-h 1s infinite linear;
}

@keyframes nc-loop-clock-anim-h {
  0% {transform:rotate(90deg)}
  100% {transform:rotate(450deg)}
}

@keyframes nc-loop-clock-anim-m {
  0% {transform:rotate(0)}
  100% {transform:rotate(360deg)}
}

If you are using an icon manager like Nucleo to manage all your icons, you can store your animations right within the SVG icon code:

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
  <g>
    <!-- svg content here -->
  </g>
  <style>
    /* CSS animation here */
  </style>
</svg>

The application displays a play button for icons that contain an animation that can be triggered with a click:

SVG fill and stroke
Store animated icons in the Nucleo application

The ability to animate distinct elements within a single SVG opens up a vast array of animation possibilities using just CSS. Below are a few more examples of animations:


The end! Check our documentation tutorials page for more articles on working with icons.

Preview of the Nucleo icons

Cookie Compliance

We use cookies to give you the best possible website experience. Learn more.