SVG-иконки

Адаптивный дизайн — популярная тема. Экраны давно вышли за пределы стандартных разрешений, и сайты могут смотреть и на девайсах размером с ладонь, и на больших мониторах. Сайт должен одинаково хорошо выглядеть вне зависимости от размера устройства и плотности пикселей. Для адаптации дизайна и контента существует много разных методик и технологий. Векторная графика, SVG, по-моему, одна из самых интересных тем в этом направлении.

SVG-графику удобно использовать для иконок, при этом они не будут выглядеть мыльными на устройствах с ретиной и их можно растягивать без потери качества.

Вот, например, один SVG-спрайт в 4-х разных размерах, исходный — 32px:

See the Pen Svg-icons: one sprite, four sizes by yoksel (@yoksel) on CodePen.

SVG отлично справляется с этой задачей и хорошо подойдет для использования в адаптивных раскладках.

Иконки для дизайна можно взять из готовых наборов или нарисовать свои.

Наборы готовых иконок

iconmelon.com

Большая коллекция иконок на разные темы. Загруженные иконки предлагается вставлять в HTML с помощью use.

От автора проекта есть вдохновляющая статья про SVG-иконки, анимации и эффекты: SVG icons FTW.

icomoon.io

Удобнейший инструмент. Можно не только выбрать и скачать готовые иконки, но также можно загрузить свои и получить их в виде шрифта и/или спрайта. Вместе со спрайтом предлагается загрузить его PNG-версию.

flaticon.com

Большая коллекция, иконки удобно поделены на категории. Выбранные иконки можно скачать в отдельных форматах (шрифт, SVG, PNG) или во всех сразу.

Рисуем сами

Для создания своего набора иконок потребуется векторный редактор:

  • Adobe Illustrator — по-моему, лучший. 599 руб./месяц в составе подписки на Creative Cloud;
  • Inkscape — бесплатный и не очень удобный;
  • Sketch — для Mac OS, $79.99. Имеет некоторые проблемы с векторизацией обводок, но вообще довольно удобный.

Снижение веса

Готовый SVG-файл обычно содержит много лишнего, но при этом хорошо поддается оптимизации. Из кода удаляются ненужные атрибуты, пробелы и переносы, а в числах уменьшается количество знаков после точки. Вес файла уменьшается на 30-50%. Инструменты для оптимизации:

petercollingridge.appspot.com/svg-optimiser github.com/svg/svgo github.com/sindresorhus/grunt-svgmin

grunt-svgmin — задача для Grunt с использованием svgo. При этом файлы сами будут браться из папки с исходниками, оптимизироваться и складываться в папку с результатами. Очень удобно.

Спрайт или иконочный шрифт?

Шрифт — удобная альтернатива спрайту. Не надо заморачиваться сеткой и расположением иконок, удобно добавлять новые символы, хотя для этого требуются дополнительные инструменты.

С помощью шрифта можно делать не только однотонные иконки, но и разноцветные.

Свой шрифт можно сделать, например, на сайте icomoon.io/app/. Примерная последовательность действий:

  1. Выберите иконки из набора и/или загрузите свои.
  2. Кликните внизу кнопку Font.
  3. На этом шаге можно переназначить символы для иконок или сразу загрузить получившийся шрифт.

Вместе со шрифтом в четырех форматах (.woff, .svg, .ttf, .eot) загружается CSS и демо-файл.

Встраиваемые шрифты работают даже в 8-м IE, но при этом имеют неожиданные проблемы с поддержкой в некоторых современных браузерах. Opera Mini вообще не поддерживает кастомные шрифты, Firefox’у требуются заклинания для сервера, где лежит шрифт (решается с помощью base64), Chrome может выгрузить шрифт, если вы надолго оставили вкладку открытой:

также в Chrome на Windows7 страница со встраиваемыми шрифтами может зависать при открытии, а в некоторых других браузерах вместо иконок может оказаться всё что угодно:

Картинка из статьи Криса Коэра Icon System with SVG Sprites. Я на этом же месте как-то видела иероглифы, но сейчас там SVG, так что скрин сделать не получится. CSS-tricks, кстати, очень активно использует SVG в своем новом дизайне, а разработчики Codepen в новом дизайне редактора отказались от использования иконочных шрифтов в пользу SVG.

Ещё одна статья в поддержку SVG: Ten reasons we switched from an icon font to SVG.

Несмотря на удобство использования, проблемы поддержки шрифтов в данный момент заставляют сделать выбор в пользу иконок на SVG.

Хочется надеятся, чтоб в будущем встраиваемые шрифты будут лучше поддерживаться.

Как существуют способы вставки SVG на страницу?

Спрайт

 .icon {
    background-image: url(your.svg);
    }

Плюсы:

  • короткий читабельный код;
  • картинка кешируется;
  • хорошая поддержка браузерами: все, кроме Оперы на Presto и старых IE.

Минусы:

  • запрос к серверу;
  • в старых Операх фоновый SVG поддерживается странно: могут возникать проблемы при добавлении рамки элементу с SVG-фоном, а в Opera Mini работают только фоны без viewBox;
  • иконки в спрайте недоступны для стилей страницы;
  • большие спрайты могут вызывать проблемы с производительностью.

Base64 в data URI

.icon {
    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL...);
    }

Плюсы:

  • нет запроса к серверу.
  • хорошая поддержка браузерами: все, кроме Оперы на Presto и старых IE.

Минусы:

  • картинка не кешируется и каждый раз рендерится заново;
  • длинная строка в CSS;
  • не читабельно: по коду непонятно что он содержит;
  • закодированная картинка может весить больше исходной;
  • для закодирования/раскодирования нужны дополнительные инструменты;
  • иконки недоступны для стилей страницы.

SVG в data URI

.icon {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns=...");
    }

Плюсы:

  • нет запроса к серверу;
  • относительно читабельный код (можно прочитать или отредактировать);
  • не требует раскодирования;
  • поддерживается всеми современными браузерами, если закодировать SVG.

Минусы:

  • не кешируется;
  • длинная строка в CSS;
  • иконки недоступны для стилей страницы;
  • поддерживается только браузерами на Webkit.

Use (переиспользование SVG-элементов)

<svg width="48px" height="48px" viewbox="0 0 32 32"><use xlink:href='#d'/></svg>

Плюсы:

  • читабельный код;
  • картинкам можно добавить title и desc;
  • символы доступны для стилей страницы. Также можно задать иконкам fill="currentColor", и они будут краситься вместе с текстом.

Минусы:

  • вставляется непосредственно в HTML. Перед использованием элементы должны быть объявлены вверху страницы в инлайновом SVG. Возможно, есть более изящный способ подключения библиотеки элементов, мне не удалось найти.

Шрифт

.icon {
  content: "\6c";
  font-family: 'icomoon';
  }

Плюсы:

  • удобный код;
  • единственный из способов поддерживается в IE8 без фолбеков;
  • иконки доступны для стилей страницы, и будут краситься вместе с текстом.

Минусы:

  • если шрифт не загрузился (ещё не загрузился, вообще не загрузился или уже выгрузился), вместо иконок будут буквы или символы юникода или ничего.

Живой пример с поддержкой браузерами:

See the Pen xDIiq by yoksel (@yoksel) on CodePen.

Пример представлен как есть, без попыток обеспечить совместимость с разными браузерами. Вы можете открыть демо в интересующем браузере и посмотреть как в нем поддерживаются разные способы.

Отображение иконок в браузерах без поддержки SVG

В данный момент самый удобный и надежный способ вставки — в виде спрайта.

Для замены картинок в IE8 и старше можно использовать способ с множественными фонами:

.icon {
    background-image: url(your.png); /* PNG для IE6-8 */
    background-image: url(your.svg), none;
    }

Для старых Опер можно использовать такой селектор:

doesnotexist:-o-prefocus,
.icon {
  background-image: url(your.png);
  }

Таким образом можно добиться, чтобы иконки у пользователей с разными браузерами выглядели примерно одинаково.

Из существующих способов вставки иконок мне больше всего нравится шрифт. Он был бы идеальным, если бы не проблемы с поддержкой. Use мне не нравится смешиванием разметки и оформления, хотя радует доступность для CSS и возможность добавить title и desc. Есть ещё один очень хороший, но плохо поддерживаемый способ, но это тема для отдельного поста.

UPD: Большое спасибо Роме Комарову за дополненния к тексту.

UPD от 04.04.14:

  1. Дополнение от Сережи Борончиева: SVG в data URI будет работать везде, если заэскейпить строку, например, с помощью escape() (JS).
  2. Прекрасный пост от Lеа Verou: Dynamically generated SVG through SASS + A 3D animated RGB cube!. Она предлагает использовать SASS, чтобы автоматически генерировать SVG-градиенты для использования в data URI.
Ссылки по теме:
Icon System with SVG Sprites
Ten reasons we switched from an icon font to SVG
SVG Tabs (Using an SVG Shape as Template)
SVG icons FTW
Using Data URIs to Speed Up Your Website
raphaeljs.com/icons/
Data URI + SVG
grumpicon.com
Dynamically generated SVG through SASS + A 3D animated RGB cube
Cила CSS поможет тебе принять форму, SVG!
On Mobile, Data URIs are 6x Slower than Source Linking (New Research)
A Primer to Front-end SVG Hacking
SVG fallback pure CSS
Если вы нашли ошибку или неточность, вы можете отредактировать статью с помощью prose.io, а также можно написать мне в комментариях или в Twitter.
Система комментирования от Disqus