DEV Community

loading...

Using SVG icons in your React developer portfolio project

ianholden profile image Ian Holden Originally published at ianholden.co.uk ・12 min read

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 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
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 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:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/devicons/devicon@v2.9.0/devicon.min.css">
Enter fullscreen mode Exit fullscreen mode

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

<i class="devicon-javascript-plain"></i></code></pre>
Enter fullscreen mode Exit fullscreen mode

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:

npx create-react-app svg-dev-icons
cd svg-dev-icons
Enter fullscreen mode Exit fullscreen mode

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:

<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>
Enter fullscreen mode Exit fullscreen mode

Create a component to display SVG

Directory structure

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

/src
  /components
    /icons
      /svg
Enter fullscreen mode Exit fullscreen mode

react.js

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

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;
Enter fullscreen mode Exit fullscreen mode

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:

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;
Enter fullscreen mode Exit fullscreen mode

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:

npm install classnames --save
Enter fullscreen mode Exit fullscreen mode

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:

import Icon from "./components/icons";

// ...

<Icon name="React" classes="size-xs" color="hotpink" />
Enter fullscreen mode Exit fullscreen mode

Full solution

You can view the full implementation on Code Sandbox.

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

Discussion (4)

pic
Editor guide
Collapse
fileformat profile image
Andrew Marcuse

In case Devicons doesn't have the logo you need, I wrote a search engine for SVG logos: logosear.ch/ It includes Devicons and a bunch of other sources as well.

I also made a collection of SVG logos that I've formatted consistently so they look good when used together: vectorlogo.zone/

Collapse
ianholden profile image
Ian Holden Author

Awesome! Thanks for sharing Andrew

Collapse
pauliescanlon profile image
Paul Scanlon

Hey, nice post. I do a similar thing.

paulie.dev/posts/2020/04/svg-icon-...

Collapse
ianholden profile image
Ian Holden Author

Nice! Thanks for sharing Paul and thanks for the feedback.