Skip to content

Instantly share code, notes, and snippets.

@d-ivashchuk
Created November 19, 2018 10:26
Show Gist options
  • Save d-ivashchuk/bf25351dbe196923894d19a9544c6780 to your computer and use it in GitHub Desktop.
Save d-ivashchuk/bf25351dbe196923894d19a9544c6780 to your computer and use it in GitHub Desktop.

Working with SVG in React

Dealing with SVG in React for me has always boiled down to importing the logo or an icon into component and using it in the src attribute of the image.

https://gist.github.com/d9888663c0029d105beaa95fc1c5912e

In this blog-post I will cover another way of working with SVG elements in React and show you the ways to animate complex SVGs using styled-components. All the necessary code is provided in the end of the post via Codesandbox.

The way of using SVG in the example above limited the possibilities of styling individual SVG layers and required to explicitly declare SVG in component to utilize all the benefits of styled-components as can be seen from the example below.

https://gist.github.com/f66615ea7f6e350815c02e171f00f1eb

Importing SVGs as React components

After one of the latest releases of React it's finally possible to import SVG as a React component and use styled helper to style it instead.

https://gist.github.com/24208ee99fce23c6e8e3e040f322059a

Now it's not necessary to have a full-blown SVG code in your components and animating parts of SVG is as simple as using css transitions for specific parts of our icon which can be achieved by using class names. Of course the most fun part of SVG animations is the possibility to animate individual paths, shapes and texts.

Let's try to recreate React logo animation from latest version of create-react-app boilerplate with styled-components and using SVG as a React Component rather than <img>.

Preparing working environment

In this tutorial we use simple example of create-react-app. Be sure to use version later than 2.0.0 of create-react-app to follow along. To bootstrap a project with create-react-app follow simple instructions from this repo or just run the commands from the next code-block in terminal of your choice. Note that you need to have Node installed to use npm commands.

https://gist.github.com/377134f389ddbf8c8e824f71d93f24b0

This will create a new React project we will work with. If you have never worked with React I highly encourage you to check out the docs so you can better follow the next steps.

Animating react logo with styled-components

In App.js import styled components and import React logo as React Component.

https://gist.github.com/a296059af377688ac4f271182cffd9bb

Declare styled version of our Logo where we will write our styles. We will add some CSS to adjust size and position.

https://gist.github.com/86ab072df1bac8688c5f8a434f1a38e0

Delete img logo and use our StyledLogo instead of it.

https://gist.github.com/9cf59880f1069fb9687f89b1f5ae0e4a

Nothing is supposed to change by now except lack of rotating animation. We can quickly fix that by importing keyframes helper from styled-components and add this simple animation.

https://gist.github.com/1d3d996afbded51161c28814c89126d0

Now you see that everything look as good as it looked originally. You may ask

Why would we even import SVG like that as it makes the workflow more complex?

The answer is simple, if you are a fan of styled-components and love animations it's really easy to animate complex SVGs (ones that consist of several elements as I've already mentioned above). Moreover we get almost unlimited flexibility in terms of adjustment of the animations and any other CSS styles based on props!

Animating individual SVG elements

We are lucky and can proceed with tutorial with the same Logo as it has couple of building blocks that can be animated separately. Namely those are circle and lines that together form react logo.

Let's define the SVG parts we want to animate and give appropriate class names to them. In logo.svg lets add the following classes that correspond to elements of our SVG.

https://gist.github.com/943c65adcb18e0eb504c9c3b12447da4

Now we are ready to add two keyframes that we will use for those two blocks of our SVG. In App.js let's add the following keyframes and use them in our StyledLogo declaration. https://gist.github.com/d4eecd4497f4acc439d719f01b63c307

Note how we added animation-play-state: paused to trigger on our circle hover. It's here to show that although SVG is grouped, all the animations that correspond to specific class are independent and won't ruin neither animation applied to the group like rotate nor to specific parts of it like fade and pulse. To test it just hover the inner circle of the logo and you will see that only that animation will stop.

Wrap up

So in this tutorial we covered the new way of importing SVG, basic animations with styled-components and css-transitions and the way to independently animate individual parts of our complex SVG component. Keep in mind that using classes with styled-components is not the most preferred way and you could achieve the same result by explicitly declaring SVG in the component and use SVG selectors to create styled versions of all paths and shapes like styled.path or styled.circle. Using our example from the start it would look like this:

https://gist.github.com/877051caa5246370d5cb355f9e2756e1

However it's more verbose and requires to keep SVG code directly in the component.

As promised here is the code! I've also added configurability to our animations by creating an arrow function that accepts props and returns styled-components keyframes. This allows to set the ad hoc values for specific CSS properties. But as it is more complex topic I will write another post dedicated to it, for now feel free to look at this code and use it if you find it helpful!


Thanks for reading! I hope you've enjoyed reading this post as much as I've enjoyed writing it! If you have any questions or want to bring up a discussion don't hesitate to reach out to me on twitter.

I highly encourage you to try styled-components for styling react applications, I've been using it for the past year and can say that I'm in love with this technology!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment