Using SVG icons in your React developer portfolio project
Tags: svg, react, codenewbie
Published: 2021-01-24 08:27:53

Have you needed icons in your React web project but were unsure of how to implement them? I use SVG icons on my [personal portfolio site](https://ianholden.co.uk) and have recently updated the way that I include them. I would like to describe my chosen method in this article.

## What is SVG?

SVG is the format for creating Scalable Vector Graphics. This means that you are able to create visuals that are defined with vectors instead of pixels. They are an alternative to other rasterised image formats such as JPG and PNG (for example).

Rasterised graphic formats such as JPG and PNG are great for storing densely populated images that include lots of variations in colour. A landscape of a forest, for example, would have many different shades of green, blue and brown for the leaves, sky and ground respectively. A scene like this would be hard to recreate using SVG.

SVG's intended purpose is for creating simpler graphics; graphics that contain fewer colours and defined shapes. They also offer a host of other benefits that are not available to us in a pixel-based format.

##Why would we use SVG?

SVGs provide many benefits. Their payload is typically **smaller** than that of a JPG or PNG because SVGs are stored as XML. This allows our graphics to be **indexed**.

SVGs are totally **scalable** because they are designed with vectors. This allows us to enlarge, shrink and print the graphic at any resolution and the graphic will still look crisp.

SVGs give us more control over our graphic and how we might transform it with code. Because SVGs are stored as XML, we are able to interact with it from within our project markup. This gives us the potential to **animate** and **transform** our graphics on the fly using JavaScript and CSS.

## Finding SVGs for my React project

On my portfolio website, I use many different SVGs to highlight the web technologies that I have used and also to highlight the methods to contact me (social media, email, GitHub).

![Gatsby, WordPress, React and AWS icons](https://s3-eu-west-2.amazonaws.com/ianholden.co.uk-wordpress-media/wp-content/uploads/2021/01/21091208/Screenshot-2021-01-21-at-09.11.40-1024x297.png)
These web technology icons are SVGs that describe the technologies used to create my portfolio website.

### Sourcing icons from Devicon

My first task is to source the icons that I would like to use in my project. This article applies to any SVG that you would like to use, however, if you are looking to use icons for a web development portfolio, I can not recommend [Devicon](https://devicon.dev/) highly enough!

Devicon offers a couple of ways to use their icons in your project.

#### Import icon font

You can access all the icons from Devicon by importing their CSS font. This is a simple import in the `<head>` of your markup:

```html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.9.0/devicon.min.css">
```

To use an icon from the icon font, you can use the following markup:

```html
<i class="devicon-javascript-plain"></i></code></pre>
```

This approach is fine and will work. However, for my project, it didn't offer as much flexibility as I would have liked. I also didn't like the idea of adding another HTTP request for the CSS stylesheet when I knew that I would only use a few of the icons from Devicon.

I opted to use another method.

#### Use raw SVGs in custom components

As well as an icon font, Devicon offers each icon as raw SVG via their GitHub repository or via their website interface. I opted to use the raw SVG in my project for a few reasons:

- It will give me greater control over the SVG within my code; allowing me to animate the icon if I would like to.
- I can make simple changes on the fly by incorporating prop values into the SVG.
- I can optimise the SVG however I like.

## Implementing an SVG component in my React project

### Create React project

Our first task is to create a new React project. For speed, we can use the create-react-app template by running the following command in our command-line interface:

```bash
npx create-react-app svg-dev-icons
cd svg-dev-icons
```

### Import SVGs from Devicon

Find an icon that you would like to use from Devicon and copy the raw SVG to your clipboard. For this tutorial, we are going to use the React icon:

```html
<svg viewBox="0 0 128 128">
  <g fill="#61DAFB">
    <circle cx="64" cy="64" r="11.4"></circle>
    <path d="M107.3 45.2c-2.2-.8-4.5-1.6-6.9-2.3.6-2.4 1.1-4.8 1.5-7.1 2.1-13.2-.2-22.5-6.6-26.1-1.9-1.1-4-1.6-6.4-1.6-7 0-15.9 5.2-24.9 13.9-9-8.7-17.9-13.9-24.9-13.9-2.4 0-4.5.5-6.4 1.6-6.4 3.7-8.7 13-6.6 26.1.4 2.3.9 4.7 1.5 7.1-2.4.7-4.7 1.4-6.9 2.3-12.5 4.8-19.3 11.4-19.3 18.8s6.9 14 19.3 18.8c2.2.8 4.5 1.6 6.9 2.3-.6 2.4-1.1 4.8-1.5 7.1-2.1 13.2.2 22.5 6.6 26.1 1.9 1.1 4 1.6 6.4 1.6 7.1 0 16-5.2 24.9-13.9 9 8.7 17.9 13.9 24.9 13.9 2.4 0 4.5-.5 6.4-1.6 6.4-3.7 8.7-13 6.6-26.1-.4-2.3-.9-4.7-1.5-7.1 2.4-.7 4.7-1.4 6.9-2.3 12.5-4.8 19.3-11.4 19.3-18.8s-6.8-14-19.3-18.8zm-14.8-30.5c4.1 2.4 5.5 9.8 3.8 20.3-.3 2.1-.8 4.3-1.4 6.6-5.2-1.2-10.7-2-16.5-2.5-3.4-4.8-6.9-9.1-10.4-13 7.4-7.3 14.9-12.3 21-12.3 1.3 0 2.5.3 3.5.9zm-11.2 59.3c-1.8 3.2-3.9 6.4-6.1 9.6-3.7.3-7.4.4-11.2.4-3.9 0-7.6-.1-11.2-.4-2.2-3.2-4.2-6.4-6-9.6-1.9-3.3-3.7-6.7-5.3-10 1.6-3.3 3.4-6.7 5.3-10 1.8-3.2 3.9-6.4 6.1-9.6 3.7-.3 7.4-.4 11.2-.4 3.9 0 7.6.1 11.2.4 2.2 3.2 4.2 6.4 6 9.6 1.9 3.3 3.7 6.7 5.3 10-1.7 3.3-3.4 6.6-5.3 10zm8.3-3.3c1.5 3.5 2.7 6.9 3.8 10.3-3.4.8-7 1.4-10.8 1.9 1.2-1.9 2.5-3.9 3.6-6 1.2-2.1 2.3-4.2 3.4-6.2zm-25.6 27.1c-2.4-2.6-4.7-5.4-6.9-8.3 2.3.1 4.6.2 6.9.2 2.3 0 4.6-.1 6.9-.2-2.2 2.9-4.5 5.7-6.9 8.3zm-18.6-15c-3.8-.5-7.4-1.1-10.8-1.9 1.1-3.3 2.3-6.8 3.8-10.3 1.1 2 2.2 4.1 3.4 6.1 1.2 2.2 2.4 4.1 3.6 6.1zm-7-25.5c-1.5-3.5-2.7-6.9-3.8-10.3 3.4-.8 7-1.4 10.8-1.9-1.2 1.9-2.5 3.9-3.6 6-1.2 2.1-2.3 4.2-3.4 6.2zm25.6-27.1c2.4 2.6 4.7 5.4 6.9 8.3-2.3-.1-4.6-.2-6.9-.2-2.3 0-4.6.1-6.9.2 2.2-2.9 4.5-5.7 6.9-8.3zm22.2 21l-3.6-6c3.8.5 7.4 1.1 10.8 1.9-1.1 3.3-2.3 6.8-3.8 10.3-1.1-2.1-2.2-4.2-3.4-6.2zm-54.5-16.2c-1.7-10.5-.3-17.9 3.8-20.3 1-.6 2.2-.9 3.5-.9 6 0 13.5 4.9 21 12.3-3.5 3.8-7 8.2-10.4 13-5.8.5-11.3 1.4-16.5 2.5-.6-2.3-1-4.5-1.4-6.6zm-24.7 29c0-4.7 5.7-9.7 15.7-13.4 2-.8 4.2-1.5 6.4-2.1 1.6 5 3.6 10.3 6 15.6-2.4 5.3-4.5 10.5-6 15.5-13.8-4-22.1-10-22.1-15.6zm28.5 49.3c-4.1-2.4-5.5-9.8-3.8-20.3.3-2.1.8-4.3 1.4-6.6 5.2 1.2 10.7 2 16.5 2.5 3.4 4.8 6.9 9.1 10.4 13-7.4 7.3-14.9 12.3-21 12.3-1.3 0-2.5-.3-3.5-.9zm60.8-20.3c1.7 10.5.3 17.9-3.8 20.3-1 .6-2.2.9-3.5.9-6 0-13.5-4.9-21-12.3 3.5-3.8 7-8.2 10.4-13 5.8-.5 11.3-1.4 16.5-2.5.6 2.3 1 4.5 1.4 6.6zm9-15.6c-2 .8-4.2 1.5-6.4 2.1-1.6-5-3.6-10.3-6-15.6 2.4-5.3 4.5-10.5 6-15.5 13.8 4 22.1 10 22.1 15.6 0 4.7-5.8 9.7-15.7 13.4z">
    </path>
  </g>
</svg>
```

### Create a component to display SVG

#### Directory structure

Create a few directories so that your file structure looks like this:

```
/src
  /components
    /icons
      /svg
```

#### react.js

Inside your new `/svg` directory, create a file named `react.js` and add the following code:


```javascript
import React from "react";

const Icon = ({color}) => (
  <svg viewBox="0 0 128 128">
    <g fill={color}>
      <circle cx="64" cy="64" r="11.4"></circle>
      <path d="M107.3 45.2c-2.2-.8-4.5-1.6-6.9-2.3.6-2.4 1.1-4.8 1.5-7.1 2.1-13.2-.2-22.5-6.6-26.1-1.9-1.1-4-1.6-6.4-1.6-7 0-15.9 5.2-24.9 13.9-9-8.7-17.9-13.9-24.9-13.9-2.4 0-4.5.5-6.4 1.6-6.4 3.7-8.7 13-6.6 26.1.4 2.3.9 4.7 1.5 7.1-2.4.7-4.7 1.4-6.9 2.3-12.5 4.8-19.3 11.4-19.3 18.8s6.9 14 19.3 18.8c2.2.8 4.5 1.6 6.9 2.3-.6 2.4-1.1 4.8-1.5 7.1-2.1 13.2.2 22.5 6.6 26.1 1.9 1.1 4 1.6 6.4 1.6 7.1 0 16-5.2 24.9-13.9 9 8.7 17.9 13.9 24.9 13.9 2.4 0 4.5-.5 6.4-1.6 6.4-3.7 8.7-13 6.6-26.1-.4-2.3-.9-4.7-1.5-7.1 2.4-.7 4.7-1.4 6.9-2.3 12.5-4.8 19.3-11.4 19.3-18.8s-6.8-14-19.3-18.8zm-14.8-30.5c4.1 2.4 5.5 9.8 3.8 20.3-.3 2.1-.8 4.3-1.4 6.6-5.2-1.2-10.7-2-16.5-2.5-3.4-4.8-6.9-9.1-10.4-13 7.4-7.3 14.9-12.3 21-12.3 1.3 0 2.5.3 3.5.9zm-11.2 59.3c-1.8 3.2-3.9 6.4-6.1 9.6-3.7.3-7.4.4-11.2.4-3.9 0-7.6-.1-11.2-.4-2.2-3.2-4.2-6.4-6-9.6-1.9-3.3-3.7-6.7-5.3-10 1.6-3.3 3.4-6.7 5.3-10 1.8-3.2 3.9-6.4 6.1-9.6 3.7-.3 7.4-.4 11.2-.4 3.9 0 7.6.1 11.2.4 2.2 3.2 4.2 6.4 6 9.6 1.9 3.3 3.7 6.7 5.3 10-1.7 3.3-3.4 6.6-5.3 10zm8.3-3.3c1.5 3.5 2.7 6.9 3.8 10.3-3.4.8-7 1.4-10.8 1.9 1.2-1.9 2.5-3.9 3.6-6 1.2-2.1 2.3-4.2 3.4-6.2zm-25.6 27.1c-2.4-2.6-4.7-5.4-6.9-8.3 2.3.1 4.6.2 6.9.2 2.3 0 4.6-.1 6.9-.2-2.2 2.9-4.5 5.7-6.9 8.3zm-18.6-15c-3.8-.5-7.4-1.1-10.8-1.9 1.1-3.3 2.3-6.8 3.8-10.3 1.1 2 2.2 4.1 3.4 6.1 1.2 2.2 2.4 4.1 3.6 6.1zm-7-25.5c-1.5-3.5-2.7-6.9-3.8-10.3 3.4-.8 7-1.4 10.8-1.9-1.2 1.9-2.5 3.9-3.6 6-1.2 2.1-2.3 4.2-3.4 6.2zm25.6-27.1c2.4 2.6 4.7 5.4 6.9 8.3-2.3-.1-4.6-.2-6.9-.2-2.3 0-4.6.1-6.9.2 2.2-2.9 4.5-5.7 6.9-8.3zm22.2 21l-3.6-6c3.8.5 7.4 1.1 10.8 1.9-1.1 3.3-2.3 6.8-3.8 10.3-1.1-2.1-2.2-4.2-3.4-6.2zm-54.5-16.2c-1.7-10.5-.3-17.9 3.8-20.3 1-.6 2.2-.9 3.5-.9 6 0 13.5 4.9 21 12.3-3.5 3.8-7 8.2-10.4 13-5.8.5-11.3 1.4-16.5 2.5-.6-2.3-1-4.5-1.4-6.6zm-24.7 29c0-4.7 5.7-9.7 15.7-13.4 2-.8 4.2-1.5 6.4-2.1 1.6 5 3.6 10.3 6 15.6-2.4 5.3-4.5 10.5-6 15.5-13.8-4-22.1-10-22.1-15.6zm28.5 49.3c-4.1-2.4-5.5-9.8-3.8-20.3.3-2.1.8-4.3 1.4-6.6 5.2 1.2 10.7 2 16.5 2.5 3.4 4.8 6.9 9.1 10.4 13-7.4 7.3-14.9 12.3-21 12.3-1.3 0-2.5-.3-3.5-.9zm60.8-20.3c1.7 10.5.3 17.9-3.8 20.3-1 .6-2.2.9-3.5.9-6 0-13.5-4.9-21-12.3 3.5-3.8 7-8.2 10.4-13 5.8-.5 11.3-1.4 16.5-2.5.6 2.3 1 4.5 1.4 6.6zm9-15.6c-2 .8-4.2 1.5-6.4 2.1-1.6-5-3.6-10.3-6-15.6 2.4-5.3 4.5-10.5 6-15.5 13.8 4 22.1 10 22.1 15.6 0 4.7-5.8 9.7-15.7 13.4z"></path>
    </g>
  </svg>
);

export default Icon;
```

This is going to be how we import our SVGs into our project. For every new SVG that you would like to use in your project, you will need to create a new  JS file like the one above and replace the SVG content with that of the new icon.

We could go ahead and use this component in our project, however, I prefer to create a container that will customise the SVG and add additional markup.

#### index.js

Create an `index.js` file in our `/icons` directory. Add the following code:

```javascript
import React from "react";
import classNames from "classnames";
import ReactIcon from "./svg/react.js";

const tidy = (string) => string.toLowerCase().trim();

const getIcon = (name, color = "#494949") => {
  switch (tidy(name)) {
    case "react":
      return <ReactIcon color={color} />;
    default:
      return "";
  }
};

const Icons = ({ name, classes, color }) => (
  <div id={`${tidy(name)}-logo-icon`} className={classNames("icon", classes)}>
    {getIcon(tidy(name), color)}
  </div>
);

export default Icons;
```

There are a few things happening in this file. 

Firstly, we have installed the 'classnames' package to help us pass through CSS classes to our new component. To use this, you must run the following command in your terminal:

```bash
npm install classnames --save
```

We have set up a few props for our new component. 

Our first is a `name` prop that we will use to select which icon we would like to return to our project. 

The second is a `classes` prop which will allow us to apply additional classes to the component.

The third is a `color` prop which we will use to change the colour of the icon. We have set a default value for this prop so that it becomes optional.

### Using our SVG component

 To use our new Icon component, we can import it into the files that require it and supply the required props like so:

```javascript
import Icon from "./components/icons";

// ...

<Icon name="React" classes="size-xs" color="hotpink" />
```

## Full solution

You can view the full implementation on [Code Sandbox](https://codesandbox.io/s/svg-icons-in-react-with-devicon-4y90e?file=/src/App.js).

{% codesandbox svg-icons-in-react-with-devicon-4y90e %}

Do you have any other smart ways of working with SVGs in React? I would love to hear about them in the comment section.