A Working SVG Workflow for Accessible Icons

It has been commonly admitted that using fonts for icons is a bad practice. It’s bad for rendering (sizing, positioning, etc.), it has weird failures (proxy browsers, CORS, etc.), it conveys poor semantics, can hurt accessibility, and the list goes on. CSS-Tricks has an insightful piece on the matter.

That being said, I always find it a bit complex to deal with SVG. Let’s be honest, I’m no Sara Soueidan. SVG is not really my thing. All these paths, weird tags, and attributes, ugh. I don’t really know how to use them. Still, I have to. And still, I like to do things properly.
So I came up with an SVG workflow for icons that is both simple and automated. Took me a bit of time to end up here, but I’m happy to write about it now that it works pretty well. Hopefully, it will be useful to some of you.

What’s the Gist?

CSS-Tricks has a very nice article by Chris Coyier about how to build an icon system with SVG sprites. Given that this article is a direct application of Chris’s article, I suggest you read it if you haven’t already.
Here is roughly how it works.
  1. Source icons are gathered in individual SVG files in a dedicated folder.
  2. A sprite is generated with spritesh.
  3. The sprite is included in the main layout for future reference.
  4. Icons are displayed through a small component.
  5. ???
  6. Profit.
The setup depends a bit on the type of project you are working on (Jekyll, React, Rails…) but the gist of it stays the same. In this article, I’ll walk you through the steps so you can start using it today.

Gathering Icon Files

If you ask me, this is somewhat of a hard part, because having correct SVG files is not an easy topic. Depending on which tool is used to export the icon, the markup looks different, can be bloated, and so on. And don’t get me started on viewBox issues…
If you can avoid designing your own icons, I’d recommend you do that. Icomoon has a very decent collection of lovely icons that are free to use and exportable as SVG. You could not wish for more. Which is why we will go this way in this article.
Icomoon icons
First, select the icons you need. Once you are done, click on “Generate SVG & More”. You should see listed all the icons you chose. Now you can download the bundle from Icomoon. The generated zip contains everything you need for the icons you picked (PNG files, SVG files, CSS, JavaScript, demo…). I recommend you copy the content of the SVG sub-folder (containing individual icon files), and paste it into your icon folder.
Before moving on, you will have to clean up the SVG files a bit. It is not entirely necessary per se, but I’d recommend you do that nevertheless to avoid bloating your SVG sprite with a lot of junk. Here is what the fire icon from Icomoon looks like when downloaded:



<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink" 
width="16" height="16" viewBox="0 0 16 16">
<path d="M5.016 16c-1.066-2.219-0.498-3.49 0.321-4.688 0.897-1.312 1.129-2.61 
1.129-2.61s0.706 0.917 0.423 2.352c1.246-1.387 1.482-3.598 1.293-4.445 2.817 1.969 
4.021 6.232 2.399 9.392 8.631-4.883 2.147-12.19 1.018-13.013 0.376 0.823 0.448 
2.216-0.313 2.893-1.287-4.879-4.468-5.879-4.468-5.879 0.376 2.516-1.364 5.268-3.042 
7.324-0.059-1.003-0.122-1.696-0.649-2.656-0.118 1.823-1.511 3.309-1.889 5.135-0.511 
2.473 0.383 4.284 3.777 6.197z"></path>
</svg>
So much for a ! I recommend you remove the XML definition, the initial comment, the doctype, and the SVG wrapper (because we will inline SVG by referencing the sprite), so only the actual drawn content remains:
<path d="M5.016 16c-1.066-2.219-0.498-3.49 0.321-4.688 0.897-1.312 1.129-2.61 
1.129-2.61s0.706 0.917 0.423 2.352c1.246-1.387 1.482-3.598 1.293-4.445 2.817 1.969 
4.021 6.232 2.399 9.392 8.631-4.883 2.147-12.19 1.018-13.013 0.376 0.823 0.448 
2.216-0.313 2.893-1.287-4.879-4.468-5.879-4.468-5.879 0.376 2.516-1.364 5.268-3.042 
7.324-0.059-1.003-0.122-1.696-0.649-2.656-0.118 1.823-1.511 3.309-1.889 5.135-0.511 
2.473 0.383 4.284 3.777 6.197z"></path>

Generating the Sprite

You might be asking yourself why we don’t use the sprite generated by Icomoon directly (symbol-defs.svg)? Actually, we could. You’ll see that what we are about to do is basically doing the same thing. The reasons I don’t like using the sprite are:
  • Icomoon adds a few things that are not necessary (mostly attributes) and are not always relevant (e.g. </code> filled after file name).</li> <li style="box-sizing: border-box; margin: 0px; padding: 0px; direction: ltr; position: relative;">I don’t want to go back to Icomoon to download the sprite again every time I want to add an icon to the sprite. It’s nice to have a system inside the project.</li> </ul> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> There are several ways to generate a sprite from a folder of icon files, but most of them rely on some kind of asset pipeline like Grunt or Gulp. This is why I created <a href="https://github.com/edenspiekermann/sprite.sh" style="box-sizing: border-box; color: rgb(54, 155, 200); text-decoration: none; line-height: inherit; word-wrap: break-word; padding: 5px 0px 1px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgba(54, 155, 200, 0.298039); transition: all 0.3s ease;">spritesh</a>, a Bash script that does Just That™.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> <em style="box-sizing: border-box; line-height: inherit;">Note: If you have a sprite generator that you like, please by all mean stick to it. spritesh is only a small helper for when you can’t/don’t want to load Gulp/Grunt and all the dependencies just for bundling icons.</em></p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> You can install spritesh through npm or as a gem (both being thin wrappers around the Bash script anyway):</p> <pre class=" language-bash" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-bash" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;">npm <span class="token function" style="box-sizing: border-box; color: rgb(221, 74, 104);">install</span> spritesh -g</code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> Then, run spritesh on the folder of icons. Assuming you stored the icon files in <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">assets/images/icons</code>and want to generate the sprite in the <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">_includes</code> folder, here is how it would look:</p> <pre class=" language-bash" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-bash" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;">spritesh --input assets/images/icons --output _includes/sprite.svg --viewbox <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"0 0 16 16"</span> --prefix icon-</code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> <em style="box-sizing: border-box; line-height: inherit;">Note: You might want to put this command in an <a href="https://docs.npmjs.com/cli/run-script" style="box-sizing: border-box; color: rgb(54, 155, 200); text-decoration: none; line-height: inherit; word-wrap: break-word; padding: 5px 0px 1px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgba(54, 155, 200, 0.298039); transition: all 0.3s ease;">npm script</a> to avoid retyping it every time you want to regenerate the sprite.</em></p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> Since we stripped out the <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);"><svg></code> element (and its <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">viewBox</code> attribute) from our source files, the<code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">viewbox</code> argument is necessary. Here we use <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">0 0 16 16</code> because this is what Icomoon uses in the first place.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> The <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">prefix</code> argument is not mandatory either. It just prevents any conflict with already-existing <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">id</code>attributes in the DOM when including the sprite. Should not be necessary, but I’d argue it’s a good practice to namespace the <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">id</code> attribute of the icons.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> <em style="box-sizing: border-box; line-height: inherit;">Note: If working on Windows, you will have to <a href="https://github.com/edenspiekermann/sprite.sh/issues/3#issuecomment-183680456" style="box-sizing: border-box; color: rgb(54, 155, 200); text-decoration: none; line-height: inherit; word-wrap: break-word; padding: 5px 0px 1px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgba(54, 155, 200, 0.298039); transition: all 0.3s ease;">run spritesh in git bash or Cygwin</a>.</em></p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> You should now have a sprite looking like this:</p> <pre class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;"><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>svg</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">xmlns</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>http://www.w3.org/2000/svg<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token style-attr language-css" style="box-sizing: border-box;"><span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);"> <span class="token attr-name" style="box-sizing: border-box;">style</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">="</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token property" style="box-sizing: border-box; color: rgb(153, 0, 85);">display</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span>none</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>symbol</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">id</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">'</span>icon-fire<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">'</span></span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">viewBox</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">'</span>0 0 16 16<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">'</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>path</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">d</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>M5.016 16c-1.066-2.219-0.498-3.49 0.321-4.688 0.897-1.312 1.129-2.61 1.129-2.61s0.706 0.917 0.423 2.352c1.246-1.387 1.482-3.598 1.293-4.445 2.817 1.969 4.021 6.232 2.399 9.392 8.631-4.883 2.147-12.19 1.018-13.013 0.376 0.823 0.448 2.216-0.313 2.893-1.287-4.879-4.468-5.879-4.468-5.879 0.376 2.516-1.364 5.268-3.042 7.324-0.059-1.003-0.122-1.696-0.649-2.656-0.118 1.823-1.511 3.309-1.889 5.135-0.511 2.473 0.383 4.284 3.777 6.197z<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>path</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>symbol</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> <span class="token comment" spellcheck="true" style="box-sizing: border-box; color: rgb(112, 128, 144);"><!-- Other <symbol>s… --></span> <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>svg</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span></code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> The only thing left to do is include the sprite in the main layout. If working on a Jekyll website for instance, it could be as simple as generating the sprite in the <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">_includes/</code> folder and adding this to the layout file:</p> <pre class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;">{% include sprite.svg %}</code></pre> <h2 id="creating-an-icon-component" style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-weight: 500; color: rgb(38, 38, 38); text-rendering: optimizeLegibility; line-height: 1.5; font-size: 34px; letter-spacing: -0.02em; background-color: rgb(255, 255, 255);"> Creating an Icon Component</h2> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> So far we’ve gathered icons and made a sprite. That’s nice, however, we still have to set up a convenient way to use these sprited icons. We will use a <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);"><use></code> tag inside an <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);"><svg></code> tag to reference the relevant symbol from our sprite (more on that technique <a href="https://css-tricks.com/svg-sprites-use-better-icon-fonts/" style="box-sizing: border-box; color: rgb(54, 155, 200); text-decoration: none; line-height: inherit; word-wrap: break-word; padding: 5px 0px 1px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgba(54, 155, 200, 0.298039); transition: all 0.3s ease;">in this article</a> on CSS-Tricks), like this:</p> <pre class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;"><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>svg</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">viewBox</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>0 0 16 16<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">class</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>icon icon-fire<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>use</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);"><span class="token namespace" style="box-sizing: border-box; opacity: 0.7;">xlink:</span>href</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>#icon-fire<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>use</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>svg</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span></code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> It works, but it’s not very friendly and ends up being quite annoying to deal with in the long run. Also, if we need to change the class, or the <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">viewBox</code> attribute, we’ll have to go over all the occurrences of this in the project. Not ideal at all.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> What we want is to abstract this bit of repetitive markup in a partial. In Jekyll, it could look like this:</p> <pre class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;"><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>svg</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">viewBox</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>0 0 16 16<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">class</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>icon icon-{{ include.icon }}<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>use</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);"><span class="token namespace" style="box-sizing: border-box; opacity: 0.7;">xlink:</span>href</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>#icon-{{ include.icon }}<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>use</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>svg</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span></code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> To use it, you include the partial and pass it an <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">icon</code> parameter:</p> <pre class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;">{% include icon.html icon="fire" %}</code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> Feel free to improve the partial to make it accept other parameters such as an extra class.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> In React, it could look like this:</p> <pre class=" language-javascript" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-javascript" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;"><span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">const</span> Icon <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">(</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">)</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">(</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span>svg viewBox<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">'0 0 16 16'</span> className<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span><span class="token template-string" style="box-sizing: border-box;"><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`icon icon-</span><span class="token interpolation" style="box-sizing: border-box;"><span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">${</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>icon<span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span>use xlinkHref<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span><span class="token template-string" style="box-sizing: border-box;"><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`#icon-</span><span class="token interpolation" style="box-sizing: border-box;"><span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">${</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>icon<span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">/</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">/</span>svg<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">)</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">;</span> <span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">export</span> <span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">default</span> Icon<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">;</span></code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> <em style="box-sizing: border-box; line-height: inherit;">Note: the <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">xlinkHref</code> is only available as per React 0.14. In React 0.13, you’ll have to use<code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">dangerouslySetInnerHTML</code>. More on that in <a href="http://stackoverflow.com/a/26822815" style="box-sizing: border-box; color: rgb(54, 155, 200); text-decoration: none; line-height: inherit; word-wrap: break-word; padding: 5px 0px 1px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgba(54, 155, 200, 0.298039); transition: all 0.3s ease;">this answer on Stack Overflow</a>.</em></p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> And then:</p> <pre class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;"><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>Icon</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">icon</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">'</span>fire<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">'</span></span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">/></span></span></code></pre> <h2 id="a-word-on-accessibility" style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-weight: 500; color: rgb(38, 38, 38); text-rendering: optimizeLegibility; line-height: 1.5; font-size: 34px; letter-spacing: -0.02em; background-color: rgb(255, 255, 255);"> A Word on Accessibility</h2> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> In <a href="https://www.paciellogroup.com/blog/2013/12/using-aria-enhance-svg-accessibility/" style="box-sizing: border-box; color: rgb(54, 155, 200); text-decoration: none; line-height: inherit; word-wrap: break-word; padding: 5px 0px 1px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgba(54, 155, 200, 0.298039); transition: all 0.3s ease;">this article from Léonie Watson</a>, it is recommended to add a title and a description with <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);"><title></code> and<code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);"><desc></code> respectively to the <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);"><symbol></code> definitions in the sprite, to improve accessibility.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> I fully support this, however, I tend to think that title and description are heavily dependent on context. Therefore, they are better defined at use time (in our component) rather than at definition time (in the sprite) in my opinion.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> For instance, if you use an icon alongside text, you don’t want a title to be read out loud, because text is already there for this. On the other hand, if you use an icon as only content for a button, you want a title and description to be read, so the user knows the purpose of the button.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> Here is how I would update our component to make it possible to pass a title and a description, making it highly accessible.</p> <pre class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-markup" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;">{% capture id %}{% increment uniqueid %}{% endcapture %} <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>svg</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">viewBox</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>0 0 16 16<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">role</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>img<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">class</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>icon icon-{{ include.icon }}<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">aria-labelledby</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>{% if include.title %}title-{{ id }}{% endif %}{% if include.desc %} desc-{{ id }}{% endif %}<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> {% if include.title %} <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>title</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">id</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>title-{{ id }}<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span>{{ include.title }}<span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>title</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> {% endif %} {% if include.desc %} <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>desc</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);">id</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>title-{{ id }}<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span>{{ include.desc }}<span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>desc</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> {% endif %} <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"><</span>use</span> <span class="token attr-name" style="box-sizing: border-box; color: rgb(102, 153, 0);"><span class="token namespace" style="box-sizing: border-box; opacity: 0.7;">xlink:</span>href</span><span class="token attr-value" style="box-sizing: border-box; color: rgb(0, 119, 170);"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span>#icon-{{ include.icon }}<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">"</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span><span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>use</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span> <span class="token tag" style="box-sizing: border-box; color: rgb(153, 0, 85);"><span class="token tag" style="box-sizing: border-box;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);"></</span>svg</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">></span></span></code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> The <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">{% increment %}</code> Liquid tag initialises a variable and then bumps it by one every time it is being called. In our scenario, it is called every time we include the icon partial, so for every icon.</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> <a href="https://jsfiddle.net/Lnx3kcmb/2/" style="box-sizing: border-box; color: rgb(54, 155, 200); text-decoration: none; line-height: inherit; word-wrap: break-word; padding: 5px 0px 1px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgba(54, 155, 200, 0.298039); transition: all 0.3s ease;">The React version</a> would work the same, using Lodash to get a unique id (feel free to use the implementation of your choice):</p> <pre class=" language-javascript" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-javascript" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;"><span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">import</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span> uniqueId <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span> <span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">from</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">'lodash'</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">;</span> <span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">const</span> Icon <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">(</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">)</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span> <span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">const</span> id <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span> <span class="token function" style="box-sizing: border-box; color: rgb(221, 74, 104);">uniqueId</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">(</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">)</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">;</span> <span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">return</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">(</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span>svg viewBox<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">'0 0 16 16'</span> role<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">'img'</span> className<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span><span class="token template-string" style="box-sizing: border-box;"><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`icon icon-</span><span class="token interpolation" style="box-sizing: border-box;"><span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">${</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>icon<span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span> aria<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">-</span>labelledby<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">(</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>title <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">?</span> <span class="token template-string" style="box-sizing: border-box;"><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`title-</span><span class="token interpolation" style="box-sizing: border-box;"><span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">${</span>id<span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`</span></span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">''</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">)</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">+</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">(</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>desc <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">?</span> <span class="token template-string" style="box-sizing: border-box;"><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">` desc-</span><span class="token interpolation" style="box-sizing: border-box;"><span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">${</span>id<span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`</span></span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">''</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">)</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>title <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">&&</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span>title id<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span><span class="token template-string" style="box-sizing: border-box;"><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`title-</span><span class="token interpolation" style="box-sizing: border-box;"><span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">${</span>id<span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>title<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">/</span>title<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>desc <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">&&</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span>desc id<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span><span class="token template-string" style="box-sizing: border-box;"><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`desc-</span><span class="token interpolation" style="box-sizing: border-box;"><span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">${</span>id<span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>desc<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">/</span>desc<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span>use xlinkHref<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">=</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span><span class="token template-string" style="box-sizing: border-box;"><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`#icon-</span><span class="token interpolation" style="box-sizing: border-box;"><span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">${</span>props<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">.</span>icon<span class="token interpolation-punctuation punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></span><span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">`</span></span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">/</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span> <span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);"><</span><span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">/</span>svg<span class="token operator" style="box-sizing: border-box; color: rgb(166, 127, 89); background: rgba(255, 255, 255, 0.498039);">></span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">)</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">;</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span> <span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">export</span> <span class="token keyword" style="box-sizing: border-box; color: rgb(0, 119, 170);">default</span> Icon<span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">;</span></code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> I will concede that it is extensively more verbose, but that’s not really a problem given that:</p> <ul style="box-sizing: border-box; margin: 0px 0px 1.25em 25px; padding: 0px; direction: ltr; font-size: 16px; line-height: 1.6; list-style: none; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; counter-reset: ol-counter 0; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> <li style="box-sizing: border-box; margin: 0px; padding: 0px; direction: ltr; position: relative;">The role of a component is to abstract complexity and avoid repetition.</li> <li style="box-sizing: border-box; margin: 0px; padding: 0px; direction: ltr; position: relative;">Accessibility is extremely important and should be a priority.</li> </ul> <h2 id="wrapping-things-up" style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-weight: 500; color: rgb(38, 38, 38); text-rendering: optimizeLegibility; line-height: 1.5; font-size: 34px; letter-spacing: -0.02em; background-color: rgb(255, 255, 255);"> Wrapping Things Up</h2> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> Hey, this wasn’t so bad now, was it? If we sum up, our system makes it easy to:</p> <ul style="box-sizing: border-box; margin: 0px 0px 1.25em 25px; padding: 0px; direction: ltr; font-size: 16px; line-height: 1.6; list-style: none; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; counter-reset: ol-counter 0; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> <li style="box-sizing: border-box; margin: 0px; padding: 0px; direction: ltr; position: relative;">Generate a sprite from the command line (which makes it easily pluggable in any build script) with custom options;</li> <li style="box-sizing: border-box; margin: 0px; padding: 0px; direction: ltr; position: relative;">Use the sprite and customise the output with a partial / component;</li> <li style="box-sizing: border-box; margin: 0px; padding: 0px; direction: ltr; position: relative;">Add new icons.</li> </ul> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> That sounds like a good system if you ask me! If we want to push things further, we could pipe in <a href="https://github.com/svg/svgo" style="box-sizing: border-box; color: rgb(54, 155, 200); text-decoration: none; line-height: inherit; word-wrap: break-word; padding: 5px 0px 1px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgba(54, 155, 200, 0.298039); transition: all 0.3s ease;">SVGO</a>to optimise the SVG files. Install it via npm:</p> <pre class=" language-bash" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-bash" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;">npm <span class="token function" style="box-sizing: border-box; color: rgb(221, 74, 104);">install</span> svgo spritesh --save-dev</code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> Then, make good use of npm scripts in your <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">package.json</code>:</p> <pre class=" language-javascript" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 16px; margin-bottom: 32px; padding: 1em; direction: ltr; text-shadow: rgb(255, 255, 255) 0px 1px; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; overflow: auto; border: 1px solid rgba(51, 51, 51, 0.0980392); background: rgb(249, 249, 250);"><code class=" language-javascript" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; background: transparent;"><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"scripts"</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"sprite"</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"spritesh --input assets/images/icons --output _includes/sprite.svg --viewbox '0 0 16 16' --prefix icon-"</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">,</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"presprite"</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"svgo assets/images/icons"</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">,</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"devDependencies"</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">{</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"spritesh"</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"^1.0.8"</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">,</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"svgo"</span><span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">:</span> <span class="token string" style="box-sizing: border-box; color: rgb(102, 153, 0);">"^0.6.1"</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span> <span class="token punctuation" style="box-sizing: border-box; color: rgb(153, 153, 153);">}</span></code></pre> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> Now, everytime we run the <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">sprite</code> task npm will first run <code class=" language-undefined" style="box-sizing: border-box; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-size: 1em; color: rgb(0, 0, 0); text-shadow: rgb(255, 255, 255) 0px 1px; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; padding: 3px; border-radius: 3px; background: rgb(232, 232, 232);">svgo</code> on the icon folder (which is only useful once, but might be good to keep in case we add new icons).</p> <p style="box-sizing: border-box; margin-bottom: 32px; padding: 0px; direction: ltr; font-family: Roboto, 'Helvetica Neue', Helvetica, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 28.8px; text-rendering: optimizeLegibility; color: rgb(74, 74, 74); background-color: rgb(255, 255, 255);"> There is probably room for further improvement so if you think of anything to make this SVG workflow better, please be sure to share!</p> </div>
A Working SVG Workflow for Accessible Icons A Working SVG Workflow for Accessible Icons Reviewed by Aamir Pathan on 2:27 AM Rating: 5