SECRET OF CSS

Styling Icons in React, Part I. Some tips to design and style your… | by Massimo Cassandro | Aug, 2022


From design to code

Some tips to design and style your React icons. From your vector editor through CSS, styled-components and…

Photo by russn_fckr on Unsplash

In my previous article on icons I have addressed some ways of managing a custom icon system. Now we will deal with the way to apply styles to monochromatic icons in a React environment.

You’ll find some essential information here about design. To go deeper, I recommend reading The Icon Handbook by Jon Hicks, a little dated in some parts but still very valid. You can also find many other resources on the web. Some interesting guides are available at Icon Utopia.

I think that the most common reasons for deciding to design an icon set are the need to have a unique design, consistent with the graphic layout you are drawing, or to have some icons that are not present in the set you have decided to use (mixing different sets is hardly a good idea).

To draw an icon set you need to use a vector editor such as Illustrator, Inkscape, Affinity Designer etc. Even Figma or Sketch, although not real drawing software, can be used for the design of non-complex elements, and certainly to manage the entire set of icons and its export to SVG in an easier way.

Start with some rough sketches and plan the icons you need. Before drawing, you also need to decide how to set up your canvas. Each icon is typically built in a square area. To determine the canvas size you must take into account the ease of drawing (easier if large) and how the icon appears at real size (which can be 14–16px per side or less). Very large canvases can lead to an incorrect perception of dimensions, making the icon unreadable in real size. Small ones can make it difficult to draw.

The final choice depends on the type of design you want to create and it may be useful to do some tests before making the final decision. In my experience, I usually set an area of 64 or 96px per side.

It is very important to choose dimensions that can be divided by a predefined module and by its multiples and submultiples. 64 and 96px layouts, for example, are built for an 8px module and are also divisible by 2, 4, 16 and 32.

The best way to set up an icon set is to draw each element onto an artboard. When files are exported as SVG, artboards define their viewBox, allowing you to better control the position of icons. Also, you can easily define grids and guides for each of them. Illustrator is very powerful in this regard.

1*4rmjO18Vf VReTnLQuW09A
1*DlvKqHRgg1UBJa9DtJg6cA
Icons layouts in illustrator and Inkscape

I find that managing many icons in the same file is quite cumbersome in Illustrator (especially in the export phase) and unstable in Inkscape. For this reason, when possible, I prefer to use Sketch or Figma, switching to Illustrator only for the most complex drawings.

Sketch artboards from the icon system of an old projects of mine
Sketch artboards from an old projects of mine (more on Behance)

Switching from icon fonts to SVG, my first icons were based on fill, that is the natural way for fonts.

But although using fill is easier to manage in some cases, I soon realized that using strokes offered more possibilities.

With strokes, for example, you can have different weights of the same icon simply changing its stroke-width property. Using fill instead, you have to prepare an icon for each weight you will need.

Another possibility offered by strokes is the ability to easily reuse your icons. An icon set definitely includes several commonly used glyphs that you may need to use in other projects. But with fill icons this is only possible if your designs use the same icons weight. For this reason, with fill icons, I always kept a stroke version of my glyphs for future reuse.

Two icons of the same glyph in Illustrator, in preview and outline view. The left one uses fill, and the other uses strokes
Two icons of the same glyph in Illustrator, in preview and outline view. The left one uses fill, and the other uses strokes

The image above represent the same icon in fill and stroke mode. As you can see, they look identical in preview mode, although they are structured in different ways.

You can easily stylize your icons using SVG attributes or css (more on that later). The essential css code is:

Really simple, but what if you have to manage fill and stroke together? You may have the need to include some fill icons in your stroke set (the most common case is the need to include social network logos).

We can easily solve this issue with a little trick. First, in our editor, we must take care to add a -fill (or whatever you want) suffix to the name of the icons we want to assign the fill property.

Here is an example in Sketch:

Some icons with their artboards in Sketch
Fill and stroke icons in Sketch

Now we have only to modify the gulpfile described in my previous article. The affected part is the icons_components task (lines from 15 to 50 of the previous gulpfile):

  • A new variable (is_fill_icon) is declared, it will help us to add specific lines of code when needed.
  • In the previous gulpfile, we used an external file as a template for our icon components. This version instead uses a variable declared inside our gulpfile (component_tpl). You can easily switch back if you prefer: simply delete line 31 and uncomment line 30. A new @extra_props@ string has also been added to the template, we’ll cover it later.
  • After the svgmin pipe, we use gulp-rename to check is the current icon is a filled one by performing a regex test on its file name (line 22). The result is assigned to the is_fill_icon variable. Optionally, you can remove the -fill suffix (line 23, in this example is commented since we have two icons with same basename, circle and circle-fill).
  • Then the svg tag is removed, and the resulting code is wrapped in the component_tpl variable.
  • Finally, if is_fill_icon is true, the @extra_props@ placeholder is replaced with the fillIcon={true} prop (or with an empty string if false). We use an array to handle our extra props, as we’ll use it again later for non-square icons.

Here you can see the results and the differences between a stroke icon and a fill one:

Of course, we also need to modify our base-icon.jsx file to handle the new props we are adding:

Show the result in CodeSandbox.

The fillIcon property is used to conditionally add a fill-icon class to our SVG. We use classnames to manage classes in a very easy way.

This way, we are now able to use every icon without worrying if it is a stroke or a fill one. The class assigned to the component will ensure that the necessary CSS properties are applied.

There are several ways to apply presentation properties to an icon.

The first uses SVG attributes. You can apply them to the BaseIcon component and avoid using CSS for styling. However, I don’t think this is the ideal option because it doesn’t really separate presentation from structural data, which should be a need for every project. Additionally, employing CSS properties makes organizing style properties simpler and more effective

It’s quite the same for inline CSS.

This is a basic example of what the BaseIcon component might look like using attributes or inline CSS. These two components produce the same result (running example on CodeSandbox):

A more convenient way is to use a CSS/SCSS file linked to your project. If you don’t want (or can’t) have a complete web component approach, this is certainly a better way.

But if your goal is to have a really component-based project, there are two interesting solutions: Styled Components and CSS Modules.

They are not the only techniques available. Even JSS or Tailwind, to name two of the most important, are valid ones. The choice of which one to use depends on the project you are facing, on what you like the most, etc.

Styled Components allow you to embed CSS code into your components, making them completely self-contained. They allow even more complex results, but, for our purposes, we will only need a very simple setup.

All the work is done in the base-icon file:

As you can see, it contains a styled SVG element to which all CSS properties have been assigned. This is the result:

And this the rendered markup of the first icon:

Note how a unique class has been created to avoid conflict with other components.

CSS Modules are another way to build a self-contained component.

It is perhaps an oversized technique for our use, but it makes sense in a larger environment where you have to share settings with other parts of your projects.

If you are using Create React App, CSS Modules are already configured, all you need to do is to change the extension of the CSS files to .module.css. But if you are creating a custom React configuration, you must provide the necessary changes yourself, according to your development environment. You can find a lot of resources and tutorials on the web (for example, “How to configure CSS Modules for webpack” on LogRocket Blog).

Finally, note that you can use CSS Modules with Sass files as well.

To go deeper, CSS Tricks has some interesting articles on CSS Modules.

As in the previous case, all changes are in the base-icon file:

All the CSS rules are now imported from the icons.module.css file, and applied through the styles variable.

This is what happened: the styles variable is now used to apply all CSS rules that have been imported from the icons.module.css file. This file is very identical to the previous one, with a few minor differences (like the bold prop).

The rendered output is the same as the Styled Components version. Take a look at the CSS modules SandBox for more details.

React Icon System articles:

  1. Building an Icon System in React
  2. Styling icons in React — Part I: From design to code (this article)
  3. Styling icons in React — Part II: Duotone and non-square icons (coming soon)



News Credit

%d bloggers like this: