Зачем я написала плагин для Grunt
В один прекрасный день перед нами (мной и моими коллегами) встала задача обработать большое количество SVG-иконок. Исходные данные: три десятка бесцветных SVG-изображений (их цвета задаются потом через CSS) и задача сделать из них PNG+CSS фолбек для старых браузеров.
Примерные шаги:
- Покрасить каждую иконку в нужный цвет.
- Для некоторых иконок сделать вариации другого цвета и размера.
- Собрать в PNG-спрайт.
- Написать CSS.
При этом получается две версии картинок: прозрачные исходники и те, что в спрайте. Обе версии всегда должны синхронизироваться между собой, а в идеале — иметь общий CSS c общими размерами и заливками для SVG.
Очевидно, что делать сборку руками долго, и процесс нужно автоматизировать, особенно если иметь в виду необходимость синхронизации изменений.
Если опустить второй шаг, первоначальную версию можно собрать из существующих плагинов для гранта. Правда, получается нечто странное, но конструкция работает.
Первая сборка выглядела примерно так:
- grunt-grunticon — красит и создает PNG-версии.
- grunt-spritesmith — генерит спрайт и CSS.
Это позволило быстро получить некий промежуточный результат, но меня не устроил CSS, получаемый на выходе. Например, он не содержал цвета заливки для SVG, и их потребовалось бы задавать где-то отдельно. Кроме того, чтобы получить в спрайте вариации иконок другого цвета и размера, пришлось бы дублировать SVG-исходники, а чтобы grunticon покрасил SVG-файлы в нужные цвета, их все нужно переназвать специальным образом (а перед генерацией спрайта переназвать обратно, ага).
Таким образом я пришла к необходимости сделать свой плагин для гранта, главными задачами которого были бы покраска изображений и создание вариаций нескольких цветов и размеров. Ну и генерация библиотеки SVG-символов + спрайт + CSS, чтобы два раза не вставать.
Мой плагин: svg_fallback.
(Да, я знаю что лучше использовать дефис, а ещё в названии не хватает префикса grunt, но это мой первый плагин : )
Что он делает:
- Берет папку SVG-изображений и делает из неё библиотеку символов.
- Берет ещё раз ту же папку, собирает из картинок спрайт и генерит CSS с заливками, размерами и фоновой картинкой для старых браузеров.
Название папки используется как префикс в классах и названиях файлов. Это нужно, чтобы не возникало конфликтов между разными наборами иконок, если они встретились на одной странице.
По окончании работы открывается демо-страница с результатами работы плагина (можно проверить работу и SVG, и PNG).
Выше описан самый простой сценарий, при котором исходные файлы никак не модифицируются в процессе, но самое интересное начинается, если в папку с исходниками положить файл config.json, в котором описаны желаемые изменения.
Например, можно задать цвет, который получат все иконки по умолчанию:
Сейчас плагин умеет красить только прозрачные иконки.
Другая задача: исходные SVG имеют не тот размер, который планируется использовать. Нужные размеры можно задать таким образом:
Сами SVG на странице могут быть любого размера, но для генерации PNG+CSS нужно привести исходники к конкретным размерам, которыми потом планируется пользоваться.
А вот так можно сделать несколько вариаций одного файла:
В этом случае на выходе будет, например, исходный файл heart.svg и его вариации:
heart--w50.svg heart--green.svg heart--w150--steelblue.svg
Можно задавать конфигурацию по частям, а можно написать всё сразу:
Результатом работы плагина будут три файла, названные по имени родительской папки. Например, содержимое папки myicons/ превратится в:
- myicons.svg — библиотека символов
- myicons.png — спрайт
- myicons.css — CSS с размерами иконок и заливкой для SVG.
Для использования получившихся иконок на странице нужно:
- Подключить на страницу myicons.css.
- В начале документа (после открывающего
<body>
) разместить библиотеку иконок (содержимое файла myicons.svg). - Отдельные иконки на страницу вставляются вот таким образом:
Upd: если в SVG опустить закрывающие теги (написать <use/>
, a не <use>...</use>
), в старых браузерах перестаёт работать HTML5-разметка.
Всем SVG-тегам на странице обязательно нужен закрывающий парный тег.
За уточнение спасибо mista_k.
Отображение иконки в старых браузерах обеспечивается вот таким кодом:
Подразумевается, что на странице есть класс .ie8
, по которому можно определить нужную версию IE.
Чтобы лучше понять как всё работает, можете установить пакет и заглянуть в папку svg_fallback/test/.
В процессе написания этого плагина было принято решение вынести код, отвечающий за изменение файлов, в отдельный пакет: svg-modify, который, при желании, можно использовать в виде плагина для гранта: grunt-svg-modify.
Теперь у меня есть целых два плагина : ) Правда, они решают довольно специфические задачи и врядли найдут широкое применение, но если вам нужно нужно проделать с SVG-иконками что-то подобное, они могут сэкономить вам время.
Если вы захотите их использовать, следует иметь в виду, что svg-modify, скорее всего, ещё будет дорабатываться (хочется более разумной работы с цветами), да и вообще я всё ещё изредка нахожу в плагинах баги разного размера, так что их стабильную работу обещать пока не могу (хотя и постараюсь).
Кроме того, svg_fallback писался для конкретной задачи, и, возможно, для ваших целей вам захочется изменить именование файлов или формат вывода CSS. В плагине нет таких опций, но вы можете форкнуть его и переписать на свой вкус.
Также следует уточнить, что мои познания в Js оставляют желать лучшего, и мой код может показаться вам странным. Кстати, буду признательна за советы как его улучшить.
- Ссылки по теме:
- svg_fallback
- npmjs.org/~yoksel
- gruntjs.com
- Грабли на чистом SVG