Frontender Magazine

Десять причин нашего перехода с иконочного шрифта на SVG

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

1. Разделение функций

До недавнего времени на lonelyplanet.com использовался подключённый шрифт, в котором все иконки были упакованы в один файл вместе с ним, причём глифы хранились в области частного использования Unicode. Такое решение нас полностью устраивало, поскольку для загрузки всех иконок требовался всего один HTTP-запрос, но, в то же время, данное решение ограничивало возможность управления приоритетом загрузки ресурсов.

У нас есть небольшая подгруппа иконок, отображение которых является критически важным для обеспечения качественного пользовательского опыта. Этот критерий не касается остальной части шрифта и иконок, и для нас крайне желательна загрузка второстепенных ресурсов после загрузки основного содержимого страницы. Однако, при предыдущем подходе к хранению иконок это было невозможно.

Отделение важных иконок от остальной части шрифта дало нам возможность более тонкого управления загрузкой ресурсов страницы.

Контраргумент

Объединять подключённый шрифт и иконочный шрифт вовсе необязательно, их можно хранить отдельно. Наверное, мы бы так и сделали, если бы решили остановиться на использовании иконочного шрифта.

2. Некоторые устройства не поддерживают области частного использования Unicode

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

Я уже и не помню, на каком устройстве проводил тестирование, когда обнаружил, что одна из наших иконок с «птичкой» была заменена иконкой цветной печати. Страница казалась мне дилетантской и «сломанной», что, без сомнения, послужило дополнительным стимулом для перехода на SVG.

3. Чёрные квадратики и крестики в Opera Mini

Добиться правильной поддержки и распознавания начертания шрифта никогда не было просто. Уверен, что вы все видели эту иллюстрацию отрисовки шрифта Awesome в Opera Mini:

пример

Я не буду вдаваться в подробности, так как проблемы поддержки Opera Mini и многих других платформ уже хорошо описаны в этой статье от @kaelig.

Если абстрагироваться от самой Opera Mini, я думаю, что здесь особенно важен тот момент, что мы определили то самое слепое пятно, которое мы в принципе не в состоянии контролировать. К сожалению, мы физически не можем провести тестирование на всех устройствах без исключений, потому нам следует отдавать предпочтение приёмам, при которых корректное отображение наиболее вероятно.

На данный момент, мы получаем не очень большую долю трафика с Opera Mini. Однако, важно помнить, что мы — компания, связанная с сферой туризма, и мы обязаны предоставляет свои услуги в любых условиях, при любом качестве подключения к сети. Так что нам всегда следует стремится делать наш сервис более доступным. Наибольшую уверенность в том, что пользователь увидит адекватное отображение страницы, нам предоставляют форматы SVG и PNG.

4. В последнее время поддержка иконочных шрифтов в Chrome отвратительна

В Chrome Canary и Beta недавно появилась отвратительная ошибка при отображении шрифтов. Если вы её пока не встречали, вкратце — после определённого периода неактивности страницы шрифт сбрасывается и заменяется на системный.

Когда происходит сброс шрифта, ваш текст отображается в Georgia, и, хоть это и не критически важный момент, он все же действует на нервы. А вот когда тот самый шрифт отвечает и за отображение иконок, страница внезапно заполняется мусором из чёрных квадратиков, и пользоваться нормально ей становится невозможно.

Эта ошибка проявилась как раз когда мы осуществляли переход на SVG. В результате, когда нам начали поступать первые отчёты об обнаружении этой ошибки на нашем сайте, мы уже перешли на новую систему и вздохнули с облегчением.

Контраргумент

Эта ошибка так и не добралась до официальной сборки Chrome.

5. Чётче иконки в Firefox

Мы обнаружили, что в Firefox наш шрифт отображается чуть жирнее, чем в других браузерах. Когда дело касается текста, в этом нет ничего страшного (хотя, и хорошего тоже мало), а вот из-за жирных иконок вся страница выглядит неухоженной и аляповатой. Используя SVG нам удалось добиться нормального отображения иконок во всех браузерах.

6. Не всегда есть возможность использовать генерируемый контент

Если вы хотите использовать шрифтовые иконки в CSS, вам придётся прописывать их, используя свойство content для генерируемого контента. Иногда это может быть затруднительным, потому что вы уже используете псевдоэлементы :before и :after, да и не все элементы поддерживают генерируемое содержимое.

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

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

7. Проще позиционирование

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

Используя SVG, нам стало гораздо легче их позиционировать. А для единого кроссбраузерного отображения мы используем background-size: cover, и просто делаем размеры элемента резиновыми.

8. Многоцветные иконки

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

Нам всегда была необходима поддержка многоцветных иконок для карт. Ранее, кроме иконочного шрифта мы использовали для этой цели дополнительный спрайт в формате PNG. В результате перехода на SVG мы смогли избавиться от лишнего спрайта, который для пользователя являлся дополнительным запросом, а для нас — дополнительным объектом, нуждающимся в поддержке.

Контраргумент

Многоцветный иконочный шрифт можно получить посредством наложения иконок.

Тем не менее, сделать это качественно та еще задачка: если правильное кросс-браузерное позиционирование одного глифа — это довольно непростой фокус, то с двумя всё становится ещё сложнее.

9. SVG позволяет использовать иконки с анимацией

Мы пока не воспользовались этим свойством, но, вполне возможно, что мы ещё рассмотрим такую возможность, раз уж она у нас теперь есть.

10. Нам не давала покоя мысль, что мы используем хак

Применение шрифта для отображения иконок нам всегда казалось хаком. Бесспорно, он великолепен, однако суть всё же состоит в маскировании объекта одного типа под какой-то другой.

Как насчёт преимуществ использования шрифта?

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

Стоит признать что нам было бы намного сложнее справиться с этими проблемами без огромной работы, проделанной командой Filament Group на Grunticon.

Вариативность цвета

Огромным преимуществом иконочного шрифта является его гибкость. У него нет ограничений в количестве вариаций цвета, его можно легко менять в зависимости от текущего состояния (:hover, :focus, .is-active и др.). Это редкая роскошь, которая очень способствует ускорению разработки. И это одна из причин того, почему мы так долго откладывали переход на SVG.

Наше решение

Для обеспечения схожей функциональности есть несколько решений, хотя все они пока имеют свои определенные ограничения. Мы наконец нашли собственную технику, которая нас вполне устраивает, и которая, в тоже время, находится на границе гибкости и ресурсоемкости.

В Grunticon каждая иконка объявляется отдельно, таким образом избегается использование спрайтов. Мы последовали их примеру, но, хотя мы и использовали для каждой иконки один CSS-селектор, все они были представлены в шести цветах, как показано здесь.

иконки

Так как мы всего лишь несколько раз дублировали одну и ту же иконку в одном и том же файле, его размер сжался до размера одной иконки (плюс около 50 байтов на GZIP-указатели). Это значит, что мы можем создать практически любое количество вариаций цвета почти без дополнительных затрат со стороны ресурсов. Вот пример работы этого приёма на jsFiddle.

Это решение дало нам ту гибкость, которую мы уже считали утраченной. Мы также получили дополнительное преимущество в виде более корректного отображения цветовой палитры, которого мы постепенно лишились при использовании иконочного шрифта.

С помощью этого приёма можно также без усилий применять к иконкам изменения, привязанные к состоянию, изменяя позиционирование фона.

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

Поддержка браузеров

Иконочный шрифт работает во всех браузерах вплоть до IE8, в отличие от SVG. Для нашего варианта реализации нам также нужна поддержка background-size, которая является почти такой же, как и для SVG.

Наше решение

У Grunticon реализован креативный подход к старым версиям браузеров. Он создаёт PNG-версии SVG-файлов, и передаёт их старым браузерам в зависимости от того, поддерживают они SVG, или нет.

В связи с отсутствием поддержки background-size, мы решили для старых версий браузеров использовать только часть иконок (только очень важные, такие как логотип). Мы могли бы обойтись без этого CSS-свойства, с помощью изменения размеров всех исходных SVG-файлов, однако, поскольку многие иконки используются с разными вариантами размера, мы решили использовать только иконки первостепенной важности с одинаковым размером в спрайте.

Мы также пробовали использовать этот полифил background-size, однако вскоре отказались от него. Я бы крайне не советовал его использовать, если вам нужно изменить размер больше, чем для одного-двух изображений. Обнаружилось, что его применение для более чем двух изображений приводит к постоянным сбоям в IE8.

Стоило ли оно того?

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

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

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Ian Feather
Автор:
Ian Feather
GitHub:
Ianfeather
Twitter:
@ianfeather
Сaйт:
http://ianfeather.co.uk/
Наталья Фадеева
Переводчик:
Наталья Фадеева
вКонтакте:
natatik_l
Twitter:
@very_busy_girl
GitHub:
NatalieF

Комментарии (14 комментариев, если быть точным)

Автар пользователя
operatino

Оригинал статьи ранее вдохновил не продолжать внедрять шрифтовые иконки, и делать SVG сразу.

Автар пользователя
TyVik

SVG, конечно, круто, я целиком и полностью за него, но пока не будет поддержки IE и FF - в топку. Похоже, они даже не планируют внедрять - https://frontender.info/ten-reasons-we-switched-from-an-icon-font-to-svg/

Автар пользователя
subzey

У инлайнового svg ещё большие плюсы, такие иконки можно свободно масштабировать и перекрашивать при помощи css (как всё изображение разом, так и отдельные элементы, например, svg.login-icon:hover .outline {fill: orange}).

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

Автар пользователя
TyVik

Прошу прощения, я имел ввиду svg-шрифты (вот правильная ссылка - http://caniuse.com/#feat=svg-fonts). А вот svg в иконках и элементах оформления - только за!

Автар пользователя
mistakster

TyVik, причём тут SVG-шрифты? Боюсь, что оба ваших комментария не принесли в тему никакой полезной информации.

subzey, фолбек через тег <img> очень дорогое удовольствие, мне кажется.

Мы в команде пошли путём встраивания SVG в документ. Фолбек делаем через background-image прям на тег <svg>. Выбрали такой способ исключительно ради простой смены цвета пиктограммы и, самое главное, ради возможности применять транзишины.

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

<svg xmlns="http://www.w3.org/2000/svg"> <defs> <rect id="shape-rectangle" x="1" y="1" width="30" height="30"/> <circle id="shape-circle" cx="16" cy="16" r="24"/> </defs> </svg>

В дальнейшем, любой контур мы рисуем просто ссылаясь на него.

<svg xmlns="http://www.w3.org/2000/svg" style="width: 32px; height: 32px;"> <use xlink:href="shapes.svg#shape-rectangle"></use> </svg>

Сама библиотека контуров загружается из внешего файла и кешируется браузером. А для IE, который не поддерживает ссылки на внешние фалы, библиотека загружается через XHR и кешируется в LocalStorage.

SVG в background-image — отличный вариант при ограниченной палитре цветов. Главное настроить автоматическую генерацию разных вариантов, а не делать это руками.

Автар пользователя
operatino

У инлайнового svg ещё большие плюсы, такие иконки можно свободно масштабировать и перекрашивать при помощи css (как всё изображение разом, так и отдельные элементы, например, svg.login-icon:hover .outline {fill: orange}).

@subzey SVG во внешних файлах так нельзя стилизовать из CSS?

Автар пользователя
mistakster

Роберт, нет, не получится. Стили применяются только к тому документу, в котором они определены. По этому и приходится применять inline SVG.

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

Автар пользователя
subzey

@mistakster, согласен, такие пляски несколько страшны. У меня условия несколько читерские — поддерживаются браузеры, которые скорее всего умеют индайновые svg, поэтому фоллбеки просто не используются. На крайний случай можно вставить текст в , браузер с инлайн-свг его проигнорирует, а без — покажет.

Вариант с чертовски хорош, кстати, почем бы не подгружать их как js, которой всего-то делает, что document.documentElement.appendChild()?

Автар пользователя
mistakster

@subzey, мы подумали, что раз уж загружаем их «руками», то почему бы не контролировать кеширование. Разницу между холостым запросом со статусом 304 Not Modified и вытаскиванием из локалстораджа не замеряли.

Мы в процессе поиска наиболее подходящего нам решения. Может быть что-то поменяем в последствии. А пока так.

Автар пользователя
subzey

304 Not Modified мы на проекте обходим при помощи «вечного» кэширования, Expires:_(Дата далеко в будущем)_. И даже гуглохром с его по меньшей мере странной политикой кэширования, не делает лишних запросов. Правда, если минус — нужно переименовывать файл, если он изменился (у нас это делается при билде прода). Ни в коем случае не навязываю, но может, это поможет в поисках решения.

Автар пользователя
mistakster

Спасибо большое за совет. Да, я понимаю о чём ты.

Автар пользователя
stotskii

Инструмент для тех, кто рисует иконки в Photoshop и при этом хочет экспортировать их в SVG - www.zeick.com

Автар пользователя
brevis

Аналогичные приемы использования иконочных SVG можно имеются статье "Кроссбраузерный SVG логотип": http://blog.g63.ru/?p=1738

Автар пользователя
brevis

*можно посмотреть в статье (правка к комментарию выше)