SVG Icons With Minimal Artistic Ability
July 11th, 2019
🥡 6 min read

Are you sick of the icons you have been using in your projects lately? Do you lack the artistic ability to draw a stick figure? If you answered yes (or no), please continue reading.

Since I began building things with JavaScript I have been using essentially the same icon set over and over. I often work with React and Styled Components so my go-to icon library has been Styled Icons. Styled Icons contains the same familiar icon sets we have probably all used at some point: Font Awesome, Material Design, Boxicons, etc. Even though there are thousands of choices and all of these icon collections are great in their own right, I got to the point where I couldn't find the right icons for my use cases and all my projects sort of looked the same. I thought creating my own icon set was way out of reach due to my complete lack of artistic talent. Turns out I was wrong.

Example Boxicons Chromium icon

The solution to my problem was Scalable Vector Graphics, or SVG. To get started you will need some kind of SVG editor. Here is a list of 7 free SVG editors. My personal preference is Boxy SVG, but I haven't tried any others 🙄. The great part about SVGs is that mathematical skills are more important than artistic skills. Boxy SVG has a ton of settings/options and taking the time to familiarize yourself with them is worthwhile. Here are the steps I take to create my icons with a few tips based on my experience.


Step 1 - Draw an icon

  • Change the dimensions of the canvas to 50px by 50px
  • Geometry options help size and position elements
  • Backgrounds will be transparent unless you set the fill attribute

I used the Circle and the Pie tool to create this:

  • Hints

    • Make one 120 degree pie piece
    • Copy and Paste it two times
    • Rotate the pieces to fit
    • Put a circle on top of that
    • The inner circle has a 1px white stroke
    • Match colors with a Color Dropper Tool

Step 2 - Optimize your SVG

  • Save your icon as an svg file
  • Go to OMGSVG and open your file. This web app is a cool utility that simplifies the markup required to render your svg.
  • Change settings and toggle the Show Original button to see the difference
  • Image / Markup tabs while both change based on settings
  • I generally use defaults and with Prettify Markup but customize when needed

The more complex your SVG the more dramatic the optimization:

Original original-markup

Optimized optimized-markup

An SVG looks great no matter what the size

Out final markup looks like this:

  • Drop all the xmln stuff since we are using these with inline HTML
  • Add a width attribute to the SVG or use CSS to style
// Cleaned up SVG markup
<svg width='200' viewBox='0 0 50 50'>
  <path
    d='M15.362 4.281a23 23 0 0 1 32.478 23.07l-22.898-2.16z'
    fill='#e94435'
  />
  <path
    d='M47.882 27.292a23 23 0 0 1-36.496 15.97l13.638-18.52z'
    fill='#35a755'
  />
  <path
    d='M11.569 43.37a23 23 0 0 1 4.762-39.552l9.037 21.15z'
    fill='#fabd05'
  />
  <circle cx='25' cy='25' r='8' stroke='#fff' fill='#3f84f3' />
</svg>

Step 3 - Create a Reusable React Component

  • Svg component will take name as props
  • The name prop will tell Svg what markup to return
  • Use React.Fragment shorthand <></> to return output
Svg.js
import React from 'react'

// Pass any additional props via destructuring ...rest
function Svg({ name, ...rest }) {
  // Helper function to return inner svg elements
  // Each icon has its own case
  // Throws error if no name prop is present
  const getPath = n => {
    switch (n) {
      case 'google':
        return (
          <>
            <path
              d='M15.362 4.281a23 23 0 0 1 32.478 23.07l-22.898-2.16z'
              fill='#e94435'
            />
            <path
              d='M47.882 27.292a23 23 0 0 1-36.496 15.97l13.638-18.52z'
              fill='#35a755'
            />
            <path
              d='M11.569 43.37a23 23 0 0 1 4.762-39.552l9.037 21.15z'
              fill='#fabd05'
            />
            <circle cx='25' cy='25' r='8' stroke='#fff' fill='#3f84f3' />
          </>
        )
      default:
        throw Error('name is required!')
    }
  }

  return (
    <svg viewBox='0 0 50 50' {...rest}>
      {getPath(name)}
    </svg>
  )
}

export default Svg
  • Add as many icons as you need
  • Use like any other React component

Step 4 - Other Ideas

  • Set size via passing a width / height prop or via CSS or however you style things
  • Pass fill or stroke as a prop to change up colors

Now we have the Chromium icon :

  • To simplify the concept lets add a dot icon

If our new component looked like this:

function Svg({ name, fill = 'black' }) {
  const getPath = n => {
    switch (n) {
      case 'dot':
        return (
          <>
            <circle cx='25' cy='25' r='8' fill={fill} />
          </>
        )
      case 'google':
        return (
          <>
            <path
              d='M15.362 4.281a23 23 0 0 1 32.478 23.07l-22.898-2.16z'
              fill='#e94435'
            />
            <path
              d='M47.882 27.292a23 23 0 0 1-36.496 15.97l13.638-18.52z'
              fill='#35a755'
            />
            <path
              d='M11.569 43.37a23 23 0 0 1 4.762-39.552l9.037 21.15z'
              fill='#fabd05'
            />
            <circle cx='25' cy='25' r='8' stroke='#fff' fill='#3f84f3' />
          </>
        )
      default:
        throw Error('name is required!')
    }
  }

  return <svg viewBox='0 0 50 50'>{getPath(name)}</svg>
}

We could have React code like this:

<>
  <Svg name='dot' />
  <Svg name='dot' fill='rebeccapurple' />
  <Svg name='dot' fill='orangered' />
  <Svg name='dot' fill='greenyellow' />
</>

And render:


In Closing

Now you know how to make your own icons and turn them into an easy-to-use React component. Hopefully, you agree with my premise that minimal artistic ability is required. I would argue the most important skill is understanding the features of your preferred SVG editor. There is a time investment here but I use working on these icons as a break from the more mind crunching code of my main projects. I think the result is websites and applications that look better and are more engaging for the user.


Examples From My Last Project