Implementing Icons
Icons have played an important role since the birth of the Graphical User Interface (GUI). They can either be informative — like icons next to form fields, providing additional visual clues — or actionable, like the infamous “hamburger”-icon, triggering a mobile navigation.
User experience and accessibility
The Nielsen Norman Group summarizes the use of icons like this:
A user’s understanding of an icon is based on previous experience. Due to the absence of a standard usage for most icons, text labels are necessary to communicate the meaning and reduce ambiguity.
Designers will most likely disagree with this, since they often use icons to save space, thus ditching the text labels, and relying on the user recognizing the [meaning of the] icon.
So, designers — if possible — please use icons in conjunction with a descriptive text that’s crisp and clear.
An icon should — if it’s actionable — always be wrapped in either a <button> , <label> , <details> or an <a> nchor. The wrapping element should contain a textual explanation of what is does, either as visual text, or using the aria-label -attribute. The icon itself should have the aria-hidden -attribute set to true .
As you typically add eventListeners to the wrapping-element, set pointer-events to none for the icon in CSS.
If an icon is informative, add either an aria-label -attribute, or use the <title> -tag in an <svg> .
For longer descriptions, <svg> also has a <desc> -tag
Implementations: SVG
There are many ways of implementing icons.
Nowadays, avoid bitmap formats like PNG or JPG, since these are not crisp and scalable.
Instead, use Scalable Vector Graphics: <svg> .
An <svg> can either be:
— A physical file, you can reference as:
- The src of an <img> -tag in HTML
- The xlink:href -attribute of a <use> -tag in HTML
- The url of a background-image in CSS
- The url of a mask-image in CSS
- The data -attribute of an <object> -tag (don’t)
- The src -attribute of an <iframe> -tag (don’t)
— Inline markup, that you can use:
- Directly in HTML
- As an encoded string in CSS, which can then be used as:
- background-image
- content in a pseudo-element
- mask-image
Note: Your <svg> -files should be as neutral as possible, so they can be used in multiple scenarios.
Remove attributes such as stroke and fill — these will be applied through CSS.
Let’s look at the various options.The least flexible: In an <img> tag
You should already know this:
Exit fullscreen mode
This works fine — you can control the size from CSS, but that’s about it.
fill and stroke will have to be hardcoded in the svg-file — not very flexible.
The most flexible: inline markup
If you want full control, the best way to add an <svg> -icon, is to inline it in your HTML-markup, like this:
Exit fullscreen mode
You can style it in CSS, like in this example:
Exit fullscreen mode
— But you can also add CSS classes to individual SVG elements:
Exit fullscreen mode
— And you can use all the usual CSS-tricks:
Exit fullscreen mode
Still flexible: Spritemap using <use> and <symbol>
If you’re going to use the icon in many places though, a more practical solution is a spritemap, using <use> — and <symbol> -tags.
You don’t have full control, as when using inline, but it’s good enough for most icon-use-cases.
You basically move all your <svg> -icons to one central spritemap.svg-file, and link to them, using <use> .Change the <svg> -tag to <symbol> , add an id -attribute with a unique value, and place it in the <defs> -section as in the example below:
Exit fullscreen mode
Exit fullscreen mode
Where xlink:href is the path and name of the SVG-file, and the #fragment identifier is the id of the <symbol> you want to use.
As an encoded string in CSS
It is also possible to store an <svg> directly as an encoded string in CSS.
You might have seen examples of an <svg> , encoded with base64 :
Exit fullscreen mode
It comes at a price, though:
It takes 4 characters per 3 bytes of data, plus potentially a bit of padding at the end.A better and more readable way, is to utf-8 -encode it, allowing you to basically “dump” a regular <svg> with line-breaks and spaces removed.
Since utf-8 is the default encoding, it’s not even necessary to specify it:
Exit fullscreen mode
If you want it more readable, escape each line with a backslash: \
The disadvantage of storing the encoded <svg> directly as a background-image , mask-image or content -property is duplication. You need to “dump” the <svg> for each use. A much smarter way is to store all your most used icons as CSS Custom Properties:Exit fullscreen mode
This way, you can re-use the <svg> -data in as many places as you want:
Exit fullscreen mode
You can also dynamically change an icon by using this method with background-image .
Consider this example:
Exit fullscreen mode
It creates a background-image , which by default is set to an empty <svg> .
Change the icon with a modifier-class:
Exit fullscreen mode
No new CSS required — just an update of a variable.
Coloring an <svg> -icon
All of the <svg> presentation attributes can be used as CSS properties, so if you’re in-lining your <svg> , you have all presentation options either as attributes in the markup, or as properties in CSS.
Just remember, that background-color is called fill in <svg> !
Exit fullscreen mode
Note: In <svg> , the value of the stroke-width -attribute is relative to the viewBox .
In CSS, use a unit, like px or em etc.
Duo-tone
You can style attributes like stroke and fill from CSS, but if you’re using a sprite-map, all the <svg> -icons (or: the elements within them, like path or line ) will have the same styling.
Maybe that’s what you want, but there’s one extra option:
currentColor is a reserved CSS-keyword (value), inheriting the current color (following the cascade). If you have an icon with more than one element and want some of the elements to have a different stroke or fill , do this:
Exit fullscreen mode
Exit fullscreen mode
The first line -element will use the stroke -property, the second one will use the color -property.
Coloring a background-image .
It is also possible to color an <svg> as a background-image — but it ain’t pretty!
You need to set an initial fill -value in either the physical <svg> -file or in the CSS Custom property — and you need to set it to one of the allowed values for: white ( #FFF , white etc).
In hsl , the value for “white” is: hsl(0, 0%, 100%) , so that’s the starting point.
You could also use “black” as your starting point, but for these examples it’s “white”.
Now, you can use a CSS filter to change the hue , saturation or lightness from the starting point of hsl(0, 0%, 100%) , for example:Exit fullscreen mode
Coloring a mask-image
It’s much easier to color a mask-image — and if you store your icons as CSS Custom Properties as mentioned above, you have a very flexible combination.
Place an <svg> as the url() of a mask-image -property on an element that also has a background-color .The <svg> will be “masked” with that color:
Exit fullscreen mode
It’s super-easy to change the icon and it’s color with a modifier-class:
Exit fullscreen mode
As the icon here has it’s own element ( <i> in this example):
Exit fullscreen mode
— all the usual CSS-tricks can be applied as well: transform , for example.
Converting existing SVGs to url()
I’ve created a tool, that can convert your existing SVG icons to a CSS url() , so they can be used with background-image or mask-image :
You just drag and drop an SVG-file to the preview-area. If an icon looks weird, try another import option. By default, the option “deep: remove as much” is selected. This option will try to remove as much “clutter” from the SVG as possible (unnecessary tags, comments etc.).
Usage Examples
In the examples below, I’ve visualized why inline svg, <use> or mask-image are my preferred methods when implementing <svg> -icons (the “checkmark” in the examples).
If you change the text-color, as in the “dark mode” -example, the <svg> ‘s used as <img> or background-image will not change color.Security and <svg>
[. ] Because of this ability to contain JavaScript, they are a perfect attack vector for Cross-Site Scripting on sites which allow either arbitrary file uploads or limit the file types to images and accept SVGs.
The quote above is from a blog-post entitled Protecting against XSS in SVG, outlining the security issues related to using <svg> .
<svg> is <xml> , and thus it can contain a regular <script> -block.
If you have an Icon System that automatically in-lines <svg> ‘s in your final markup, thread carefully, if content-editors are allowed to upload <svg> ‘s directly.
Exit fullscreen mode
When in-lined, the script will run, check the console .
In newer browsers, scripts will not run if the <svg> is used from either <img> -tags or via <use> .Optimizing <svg> : An example
When you receive an <svg> from a designer, it usually contains way too much unnecessary clutter.
Here’s a real-life example of a simple «close icon», I received from a designer:
Exit fullscreen mode
By using Jake Archibald’s SVGOMG-tool, a lot of the unnecessary bits can be cut off:
Exit fullscreen mode
The file went from 1571 bytes to 473 bytes.
But, for such a simple icon, we can also handcode it with two line elements:
Exit fullscreen mode
Exit fullscreen mode
Notice, that I changed width and height to viewBox , which creates a «real coordinate system» and will allow us to easier control responsiveness. Instead of fill , I used stroke .
If the <svg> is going to be used inline or in an sprite-map using symbol , we can also remove the xmlns -attribute and style-declarations ( stroke , fill etc.):
Exit fullscreen mode
That’s 77 bytes, approx. 5% of the original file-size.
To optimize <svg> ‘s automatically during a build process, read on.SvgSpritemapWebpackPlugin
This webpack-plugin generates a single SVG spritemap containing multiple elements from all .svg files in a directory. In addition, it can optimize the output and can also generate a stylesheet containing the sprites to be used directly from CSS.
Download SvgSpritemapWebpackPlugin if you’re looking for an easy way to convert a folder of .svg -files to a single spritemap. While the current version cannot generate CSS Custom Properties from the .svg -files, there are .scss and .less mixin/variables that will let you use them from CSS.
Exit fullscreen mode
SvgSpritemapWebpackPlugin can also run svgo and svg4everybody automatically, check out the official documentation.
Polyfill for using <use>
IE 11 doesn’t support <use> , so you’ll need a poly-fill (if you still need to support IE11!).
svg4everybody is a popular poly-fill for using <use> in Internet Explorer, and is highly recommended.Below is a simple example of conditionally loading svg4everybody, if the browser is IE11:
Exit fullscreen mode
Download the script from svg4everybody‘s GitHub-repo, and replace s4eUrl with the correct path.
Or link to it directly from Cloudflare or a similar CDN-service.While svg4everybody works in most cases, I had a project where <text> -elements were being added dynamically to an <svg> -shape, so editors could modify text-lines in an <svg> -shape (custom svg-splashes with product-offers) from a CMS:
Exit fullscreen mode
svg4everybody replaces <use> with the actual <symbol> -content, but it does that as the last chil_ of the parent:
Exit fullscreen mode
Thus, the <svg> -shape ended up after the <text> -lines.
As the project was already running Babel, I could write a poly-fill in ES6:Exit fullscreen mode
Implementations: CSS Icons
Sometimes a huge SVG-based Icon System might be unnecessary, if you just need a few arrows, a “close-icon” etc. There’s a classic article on css-tricks about the shapes of CSS.
I thought it could be a fun project to create a small library of CSS Icons, using some of these classic techniques, but also adding newer features like clip-path for creating even more icons using pure CSS:clip-path is — like svg — vector-based. path is not supported for clip-path yet, but when it is, you’ll have nearly as many possibilities for creating shapes and icons as in svg .
If you want to create your own icons using clip-path , I’ve made a small tool for that:
Implementations: Icon Fonts
I think we’ve all encountered a slow-loading website, where strange letters or symbols were shown instead of an icon — until the Icon Font finished loading.
That’s just one of the downsides of using an Icon font.
In the blog-post “It’s 2019! Let’s End The Debate On Icon Fonts vs SVG Icons”, <svg> is the clear winner when it comes to:- Accessibility. An <svg> is treated like an image, not as text, that will be read aloud by a screen-reader.
- Scalability. This is the main reason why I switched to using <svg> . Also, they’re easier to modify on-the-fly.
- Animation. You can animate each path , line etc. in an <svg>
Google provides an Icon font for their Material Design, so the format is not completely dead — yet.
Создаём и используем символьный SVG-спрайт

SVG — масштабируемая векторная графика.
Сама по себе технология SVG — это очень объёмная тема — подробнее с ней можно познакомится на MDN Web Docs
В данной статье мы будем использовать иконки созданные по технологии SVG. Их отличие в том, что при изменении размеров они не теряют качества отображения, при этом весят обычно меньше, чем аналогичная иконка в другом формате, например PNG
Аналогичные иконки при масштабировании в формате SVG и PNG

Способы использования SVG-иконок
SVG-иконки можно использовать несколькими способами
1й способ — сохранить SVG-иконку как файл, и подключать как обычное изображение
При таком способе подключения, SVG-иконка будет масштабироваться без потери качества, но нельзя будет задать цвет иконки через CSS, и следовательно не получится плавно менять цвет иконки при наведении. И если в другом месте нужно будет использовать эту же иконку в другом цвете, необходимо будет создавать дополнительный файл SVG иконки
2й способ — открыть файл SVG-иконки в текстовом редакторе, скопировать код иконки и вставить его в необходимую часть HTML.
Если использовать SVG-иконку таким способом, можно будет задать цвет иконки через CSS, и получится сделать плавное изменение цвета при наведении. Но если придется использовать эту же иконку в другом месте, то это будет дополнительная нагрузка на браузер, так как иконка будет отрисовываться заново при каждом использовании
3й способ — самый оптимальный способ использовать SVG-иконки — сделать символьный SVG-спрайт. При таком способе каждая иконка отрисовывается всего один раз в скрытом блоке, а затем может быть использована неограниченное количество раз, ссылаясь на уже отрисованную иконку. При этом, одной и той же иконке в разных местах можно задавать свой цвет через CSS, следовательно не нужно дублировать иконку и можно делать плавное изменение цвета при наведении.
Этот способ и рассмотрим подробнее
Создаём и используем символьный SVG-спрайт
Символьный SVG-спрайт — это просто коллекция символьных SVG-иконок, собранных в одном, обычно скрытом, специальном блоке
Для примера скачаем пару SVG-иконок, например, на сайте https://uxwing.com/ с бесплатными иконками
Чтобы автоматически создать SVG-спрайт, воспользуемся онлайн-сервисом https://svgsprit.es/
Просто перетаскиваем все необходимые файлы SVG-иконок на главную страницу https://svgsprit.es/, и внизу страницы автоматически будет сгенерирован код, состоящий из двух частей
Первая часть — символьный SVG спрайт
Вторая часть — код использования
Создадим HTML разметку, в которую добавим сгенерированный символьный SVG-спрайт и сразу используем иконки в необходимых местах
Добавим стили
Прежде чем задавать цвет иконки в CSS, необходимо убедиться, что у кода иконки в SVG-спрайте отсутствуют свойства fill и stroke . Если эти свойства присутсвуют в коде иконки, то необходимо их удалить, так как приоритет CSS свойств будет ниже, чем у inline-стилей, и значения, указанные в CSS будут игнорироваться
Чтобы через CSS задать цвет для SVG-иконки, используем свойства fill и stroke
fill — заливка иконки
stroke — цвет обводки
Если иконка состоит только из обводки, то чаще всего для свойства fill необходимо указать значение transparent , чтобы у иконки не было чёрной заливки по-умолчанию
Получаем следующий результат
Итоги
Использование SVG-иконок имеет несколько преимуществ — возможность масштабирования без потери качества, плавное изменение цвета, меньший вес, нет необходимости дублировать иконки, если они отличаются по цвету, размеру.
В статье рассмотрели как быстро и просто создать символьный SVG-спрайт и оптимально использовать SVG-иконки
Using SVG
SVG is an image format for vector graphics. It literally means Scalable Vector Graphics. Basically, what you work with in Adobe Illustrator. You can use SVG on the web pretty easily, but there is plenty you should know.
Why use SVG at all?
- Small file sizes that compress well
- Scales to any size without losing clarity (except very tiny)
- Looks great on retina displays
- Design control like interactivity and filters
Getting some SVG to work with
Design something in Adobe Illustrator. Here’s a Kiwi bird standing on an oval.

Notice the artboard is cropped up right against the edges of the design. Canvas matters in SVG just like it would in PNG or JPG.
You can save the file directly from Adobe Illustrator as an SVG file.

As you save it, you’ll get another dialog for SVG Options. I honestly don’t know much about all this. There is a whole spec for SVG Profiles. I find SVG 1.1 works fine.

The interesting part here is that you can either press OK and save the file, or press “SVG Code…” and it will open TextEdit (on a Mac anyway) with the SVG code in it.

Both can be useful.
Using SVG as an <img>
If I save the SVG to a file, I can use it directly in an <img> tag.
In Illustrator, our artboard was 612px ✕ 502px.

That’s exactly how big the image will on the page, left to itself. You can change the size of it though just by selecting the img and changing its width or height , again like you could a PNG or JPG. Here’s an example of that:
Using it this way has its own set of specific browser support. Essentially: it works everywhere except IE 8 and down and Android 2.3 and down.
If you’d like to use SVG, but also need to support these browsers that don’t support using SVG in this way, you have options. I’ve covered different techniques in different workshops I’ve done.
One way is to test for support with Modernizr and swap out the src of the image:
David Bushell has a really simple alternative, if you’re OK with JavaScript in the markup:
SVGeezy can also help. We’ll cover more fallback techniques as this article progresses.
Using SVG as a background-image
Similarly easy to using SVG as an img, you can use it in CSS as a background-image .
Notice we set the background-size to the size of the logo element. We have to do that otherwise we’ll just see a bit of the upper left of our much larger original SVG image. These numbers are aspect-ratio aware of the original size. But you could use a background-size keywords like contain if you want to make sure the image will fit and can’t know the parent image will be of the exact right size.
Using SVG as background-image has its own special set of browser support, but it’s essentially the same as using SVG as img. The only problem browsers are IE 8 and down and Android 2.3 and down.
Modernizr can help us here, and in a more efficient way than using img. If we replace the background-image with a supported format, only one HTTP request will be made instead of two. Modernizr adds a class name of “no-svg” to the html element if it doesn’t support SVG, so we use that:
Another clever progressive enhancement flavored technique for using SVG as background-image is by using it in conjunction with multiple backgrounds. SVG and multiple backgrounds have very similar browser support, so if the browser supports multiple backgrounds, it supports SVG, and the declaration will work (and override any previous declaration).
The problem with both <img> and background-image…
Is that you don’t get to control the innards of the SVG with CSS like you can with the following two ways. Read on!
Remember how you can grab the SVG code right from Illustrator while saving if you want? (You can also just open the SVG file in a text editor and grab that code.) You can drop that code right into an HTML document and the SVG image will show up just the same as if you put it in an img.
This can be nice because the image comes over right in the document and doesn’t need to make an additional HTTP request. In other words, it has the same advantages as using a Data URI. It has the same disadvantages too. A potentially “bloated” document, a big chunk of crap right in the document you’re trying to author, and inability to cache.
If you’re using a back end language that can go fetch the file and insert it, at least you can clean up the authoring experience. Like:
A little PHP-specific thing here… it was demonstrated to me that file_get_contents() is the correct function here, not include() or include_once() as I have used before. Specifically because SVG sometimes is exported with <?xml version=»1.0″ encoding=»UTF-8″?> that as the opening line, which will cause the PHP parser to choke on it.
Optimize it first
Likely not a huge shocker, but the SVG that Adobe Illustrator gives you isn’t particularly optimized. It has a DOCTYPE and generator notes and all that junk. SVG is already pretty small, but why not do all we can? Peter Collingridge has an online SVG Optimiser tool. Upload the old, download the new. In Kyle Foster’s video, he even takes it the extra mile and removes line breaks after this optimization.
If you’re even more hardcore, here is a Node JS tool for doing it yourself.
Now you can control with CSS!
See how the SVG looks a lot like HTML? That’s because they are both essentially XML (named tags with angle brackets with stuff inside). In our design, we have two elements that make up the design, an <ellipse> and an <path> . We can jump into the code and give them class names, just like any other HTML element can have.
Now in any CSS on this page we can control those individual elements with special SVG CSS. This doesn’t have to be CSS embedded in the SVG itself, it can be anywhere, even in our global stylesheet <link> ed up. Note that SVG elements have a special set of CSS properties that work on them. For instance, it’s not background-color , it’s fill . You can use normal stuff like :hover though.
Even cooler, SVG has all these fancy filters. For instance blurring. Chuck a filter in your <svg> :
Then you can apply that in your CSS as needed:
Inline SVG has it’s own set of browser support, but again, it’s essentially only an issue in IE 8 and down and Android 2.3 and down 1 .
One way to handle fallbacks for this type of SVG is:
Then use Modernizr again:
Using SVG as an <object>
If “inline” SVG just isn’t your jam (remember it does have some legit drawbacks like being hard to cache), you can link to an SVG file and retain the ability to affect its parts with CSS by using <object> .
For the fallback, Modernizr detection will work fine here:
This will work great with caching and actually has deeper support than using it any other way. But, if you want the CSS stuff to work, you can’t use an external stylesheet or <style> on the document, you need to use a <style> element inside the SVG file itself.
External stylesheets for <object> SVG
SVG has a way to declare an external stylesheet, which can be nice for authoring and caching and whatnot. This only works with <object> embedding of SVG files as far as I’ve tested. You’ll need to put this in the SVG file above the opening <svg> tag.
If you put that in your HTML, the page will barf and not even try to render. If you link up an SVG file that has that in it as an <img> or background-image , it won’t barf, but it won’t work (the SVG will still render though).
Data URL’s for SVG
Another way to use SVG’s is to convert them into Data URL’s. Data URL’s might not save you actual file size, but can be more efficient because the data is right there. It doesn’t require an additional network request.
Mobilefish.com has an online conversion tool for that base64ing them, but I generally don’t think that’s a good idea for SVG. Simply paste in the contents of your SVG file and fill out the form and it will display the results in a textarea for you to copy. Remember to remove line breaks in the data it gives you back. It looks like pure gibberish:

You can use that anywhere we’ve talked about so far (except inline <svg> because that just doesn’t make sense) Just put the gibberish where it says [data] in these examples.
This converter is my fav, as it leaves the SVG as mostly readable text:
Relevant note here: regular CSS doesn’t care if you put quotes around the data URI, but Sass does, so I’ve quoted it above (Thx Oziel Perez).
And yep, if you have an embedded <style> in your SVG before you base64 it, it will work if you use it as an <object> still!
Format for Data URI
All the examples above have base64 as the encoding, but data URI’s do not have to be base64. In fact in the case of SVG, it’s probably better NOT to use base64. Primarily because the native format of SVG is much more repetitive than base64 ends up, it gzips better.
Command line thingy for base64ing SVG:
@chriscoyier @hkfoster maybe you could take a shortcut with >>> echo -n `cat logo.svg` | base64 | pbcopy
— Benny Schudel (@bennyschudel) March 2, 2013
Use openssl base64 < path/to/file.png | tr -d ‘\n’ | pbcopy or cat path/to/file.png | openssl base64 | tr -d ‘\n’ | pbcopy to skip writing to a file and just copy the base64-encoded output to the clipboard without the line breaks.
From a CSS perspective, it’s easy to use, as it generates a class referencing each icon, and doesn’t use CSS sprites.
grunticon takes a folder of SVG/PNG files (typically, icons that you’ve drawn in an application like Adobe Illustrator), and outputs them to CSS in 3 formats: svg data urls, png data urls, and a third fallback CSS file with references to regular png images, which are also automatically generated and placed in a folder.
A PHP command line tool for converting SVG images to a set of CSS icons (SVG & PNG, single icons and / or CSS sprites) with support for image optimization and Sass output.
- David Bushell: A Primer to Front-end SVG Hacking
- David Bushell: Resolution Independence With SVG
- Browser support for a variety of different SVG related things.
- Peter Gasston: Better SVG Sprites With Fragment Identifiers
- simuari: SVG Stacks – “A lightweight library for manipulating and animating SVG.”
- Emmet has an awesome way to get a data URI from an SVG right from your code editor.
- Compass has a helper for data URIs too.
- Adobe: Styling SVG
- Andrew J. Baker: Taming the SVG Beast
- Illustrator alternatives: Inkscape, Sketch
- Krister Kari: Dealing with SVG images in mobile browsers
Kyle Foster’s An Optimized SVG Workflow, which is worth an embed:
1 And speaking of Android 2.3 browser, this. But if you absolutely have to support the native browser, this.
Установка SGV иконки

В современной разработке веб сайтов не обойтись без установки масштабируемой векторной графики — SVG (Scalable Vector Graphics), и для этого есть несколько способов установки SVG иконки со своими плюсами и минусами.
Для примера возьмем SVG иконку myicon.svg, которую будем добавлять на нашу страницу.
Установка SVG в качестве графического файла
Тут все просто, иконка ставится как обычная картинка в тег img с путем на svg файл, обязательно нужно указать параметры ширины и высоты:
Установка SVG графики в HTML
Вставляем SVG код непосредственно в нужное место HTML, недостаток в том что если картинок много, у нас получится избыточность одинакового кода:
Установка SVG через CSS
Делаем SVG графику фоновым изображением для указанного элемента. Для этого переводим SVG код в CSS формат конвертером:
Установка SVG через JS
Создаем JavaScript переменную со значением кодом иконки, а далее используем ее в нужном элементе:
Далее повторяем выше указанный вариант с CSS, вставляя нужную иконку куда угодно.