Сайт о телевидении

Сайт о телевидении

» » Стилизация SVG с помощью CSS: возможности и ограничения. Добавляем SVG на страницу с помощью тега. Как сделать кроссбраузерный SVG

Стилизация SVG с помощью CSS: возможности и ограничения. Добавляем SVG на страницу с помощью тега. Как сделать кроссбраузерный SVG

Подготовка SVG для использования в вебе это очень простой процесс, не сложнее экспорта JPEG или PNG . Используйте любой привычный для вас графический редактор (Illustrator, Sketch, Inkscape [бесплатен], и тому подобное [или даже Photoshop, если вы используете слои с формами]) с тем размером изображения, который вы планируете использовать. Обычно я работаю в Иллюстраторе, поэтому я объясню некоторые способы подготовки файлов в этой программе, но вообще они применимы и для любой другой программы. Вам, возможно, стоит перевести текст в кривые, поскольку шрифт, скорее всего, будет неправильно отображаться, если, конечно, вы не планируете стилизовать их с помощью веб-шрифта, используемого на странице (что возможно!). Не стоит также превращать все объекты в единые формы, особенно если у вас есть обводка, которой необходимо будет управлять на странице, тем более преобразование объектов зачастую не уменьшает размер файла. Любые имена, присвоенные группам или слоям, будут добавлены к SVG как ID элемента. Это довольно удобно для стилизации, но немного увеличит общий размер файла.

Перед тем как сделать экспорт, необходимо проверить, все ли изображения находятся в целочисленной пиксельной сетке (то есть, например не 23.3px × 86.8px ). В противном случае скорее всего изображению не будет хватать чёткости и часть изображения обрежется. В Иллюстраторе это можно сделать следующим образом: Object > Artboards > Fit to Artwork Bounds . Затем жмём save as и выбираем SVG , и оставляем настройки по умолчанию. Здесь можно сделать небольшую оптимизацию, но на самом деле не стоит, так как далее мы будем применять разные улучшающие приёмы, поэтому сейчас мы не будем тратить впустую время на эти настройки.

Приёмы для уменьшения размеров файла.

(Смотрите по оптимизации)

Чтобы добиться наименьшего размера SVG , логично будет удалить из него всё лишнее. Наиболее известная и полезная программа (по крайней мере я так думаю) для обработки SVG это SVGO . Она удаляет весь не нужный код. Но! Будьте внимательны используя эту программу, если планируете управлять SVG при помощи CSS / JS , так как она может слишком сильно почистить код, что затруднит дальнейшие изменения. Удобство SVGO ещё и в том, что её можно включить в процесс автоматической сборки проекта, но можно также использовать GUI если хочется.

Разбираясь подробнее с правильным удалением всего ненужного, мы можем сделать ещё кое-что в графическом редакторе. Сперва нужно убедиться, что используется настолько мало контуров/форм, насколько это возможно, так же как и точек на этих контурах. Можно объединять и упрощать всё, что поддаётся упрощению, и удалить все ненужные точки. В Иллюстраторе есть плагин VectorScribe с инструментом Smart Remove Brush Tool , который поможет удалить точки и при этом оставить общую форму той же.

Предварительная оптимизация

Smart Remove Brush Tool удалил точки

Дальше будем увеличивать изображение. В Иллюстраторе удобно включить просмотр с пиксельной сеткой View > Pixel Preview и проверить, как располагаются контуры. Чтобы разместить контуры по сетке, потребуется немного времени, но эти усилия окупятся и позволят добиться более чёткого рендеринга (лучше обратить на это внимание заранее).

Точки вне сетки

Выравнивание по сетке

Если есть два и более объекта для выравнивания, то стоит удалить все ненужные перекрытия. Иногда даже если контуры тщательно выровнены, может быть видна тонкая белая линия. Чтобы предотвратить такое, можно немного наложить объекты друг на друга в местах перекрытия. Важно: в SVG z-index имеет определённый порядок, который зависит от объекта, находящегося снизу, поэтому стоит поместить верхний объект в нижнюю часть файла в коде.

И, наконец, последнее, но немаловажное, то, о чём обычно забывают - это активировать gzip сжатие SVG на вашем сайте в.htaccess файле.

AddType image/svg+xml svg svgz AddOutputFilterByType DEFLATE "image/svg+xml" \ "text/css" \ "text/html" \ "text/javascript" ... etc

В качестве примера того, насколько эффективна эта техника, я воспользуюсь оригинальным логотипом Breaking Borders и оптимизирую его таким образом: увеличиваю размер до того, каким он должен быть; приведу в порядок контуры; удалю максимально возможное количество точек; передвину точки на целочисленные пиксели; сдвину все области перекрытий и отправлю это всё в SVGO .

Оригинал: 1,413b После оптимизации: 409b

В итоге размер файла стал меньше на ~71% (и на ~83% при сжатии)

Подробная статья об оформлении содержимого в элементе SVG и преодолении связанных с этим проблем.

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

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

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

Краткий обзор структуры SVG, группирования и ссылок на элементы в SVG

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

4 основных группирующих и связывающих элемента SVG это , , and .

Элемент (сокращение от “group”) используется для логической группировки наборов связанных графических элементов. В терминах графических редакторов (типа Adobe Illustrator) элемент по функционалу похож на функцию “Сгруппировать объекты”. Вы также можете думать о группе как о слое в графическом редакторе.

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

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

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

У элемента есть еще одно важное преимущество: он принимает атрибут viewBox , который позволяет масштабирование внутри любой области видимости.

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

Чтобы использовать элемент вам надо передать ссылку на этот элемент, идентификатор - это атрибут xlink:href и спозиционировать его, задав атрибуты x и y . Вы можете применить стили к элементу и они будут каскадироваться на содержимое этого элемента.

Но что является содержимым ? Куда он клонируется? И как каскад CSS работает с ним?

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

  • Структурирование, группировка и ссылки в SVG - Элементы g, use, defs и symbol
  • Разбираемся в системе координат SVG (Часть 1): Viewport, viewBox и PreserveAspectRatio
SVG и теневой DOM

Когда вы ссылаетесь на элемент с помощью , ваш код выглядит примерно так:

На экране отображается иконка, содержимое которой определено внутри , но на самом деле это содержимое элемента , которое является клоном .

Но элемент это всего лишь один самозакрывающийся элемент - в нем нет контента между открывающим и закрывающим тегами, так куда же клонируется содержимое ?

Ответ - в теневой DOM (почему-то он всегда у меня ассоциируется с Бэтменом, не знаю почему).

Что такое теневой DOM?

Теневой DOM идентичен обычному DOM, за исключением того, что вместо того, чтобы быть частью дерева основного документа, узлы теневого DOM относятся к фрагменту документа, который является параллельным основному, но недоступным для его скриптов и стилей. Это дает авторам возможность создавать модульные компоненты, инкапсулируя скрипты и стили. Если вы когда-либо использовали элемент video или диапазонный ввод в HTML5 и не поняли, откуда появлялись элементы управления видеоплеером или слайдер, то ответ тот же - теневой DOM.

В случае с элементом SVG , содержимое, на которое он ссылается, клонируется в фрагмент документа, “хостящийся” в . В данном случае это теневой хост.

Итак, содержимое (клон или копия элемента, на который он ссылается) присутствует внутри теневого фрагмента документа.

Другими словами, содержимое находится там, но оно невидимое. Такое же, как и содержимое обычного DOM, но не доступное высокоуровневым средствам, таким как селекторы CSS и JavaScript, скопированное в фрагмент документа, привязанный к .

Теперь, если вы дизайнер, вы можете подумать: “ОК, я понял, но есть ли способ проверить этот субдокумент и увидеть его содержимое”. Ответ - да, вы можете просматривать содержимое теневого DOM, используя инструменты разработки в Chrome (в Firefox на данный момент эта функция не доступна). Но для начала вам надо активировать инспектора теневого DOM во вкладке General на панели настроек. Это подробно описано .

После того, как вы активировали инспекцию теневого DOM в инструментах разработчика, вы можете видеть клонированные элементы на панели элементов, также как и элементы обычного DOM. На следующем изображении показан пример элемента , ссылающегося на содержимое элемента . Обратите внимание, что “#shadow-root” и его содержимое являются клоном содержимого .

Используя инструменты разработчика Chrome, вы можете инспектировать содержимое элемента use внутри теневого DOM (“#shadow-root”, строка выделена серым цветом). На этом скриншоте инспектируется логотип Codrops из примера, который мы будем рассматривать в следующем разделе.

Глядя на инспектируемый код, вы можете увидеть, что теневой DOM очень похож на обычный, за исключением того, как он обрабатывается CSS и JavaScript основного документа. Существуют также иные различия между ними, которые мы не будем рассматривать в этой статье по причине их объема, поэтому если вы хотите узнать больше, я рекомендую вам следующие статьи:

  • Теневой DOM 101 (перевод на Frontender.info)
  • Введение в теневой DOM (Видео)

С учетом моего ограниченного опыта взаимодействия с теневым DOM, я рассматриваю его как обычный DOM, который нужно по другому обрабатывать в части доступа CSS и JavaScript к его элементам. Это то, что важно для нас при работе с SVG: как воздействовать на содержимое внутри теневого DOM, ведь нам важно иметь возможность оформлять его. Весь смысл использования это возможность создавать различные копии элемента и в большинстве случаев нам надо иметь возможность стилизовать каждую копию по-разному. Например, это может быть лого в двух цветовых темах или многоцветные иконки для разных цветовых тем. Так что для нас важно иметь возможность сделать это с помощью CSS.

Как было сказано, содержимое теневого DOM недоступно для CSS в отличие от обычного DOM. Так как нам стилизовать его? Мы не можем использовать путь к потомкам типа такого:

Use path#line { stroke: #009966; }

Потому как у нас нет доступа к теневому DOM с помощью обычных CSS селекторов.

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

На самом деле, презентационные атрибуты рассматриваются как низкоуровневые “авторские таблицы стилей” и они переписываются остальными стилевыми декларациями: внешними, внутренними и инлайновыми стилями. Их единственная сила это приоритет перед унаследованными стилями. И все.

Теперь, когда мы выяснили это, вернемся к нашему элементу и его содержимому.

Мы знаем, что мы не можем задать стили внутри , используя CSS селекторы.

Но мы также знаем, что как и в случае с элементом , стили примененные к будут унаследованы всеми его потомками (которые находятся в теневом DOM).

Итак, сначала попытаемся изменить цвет заливки (fill) элемента внутри , применив селектор к самому элементу с расчетом, что каскад и наследование сделают свое дело.

Однако, это вызывает пару вопросов:

  • Цвет заливки будет унаследован всеми потомками элемента , даже теми, к которым вы не хотите применять стили (но если внутри у вас всего один элемент, то этой проблемы не будет).
  • Если вы экспортировали SVG из графического редактора или по каким-либо иным причинам не можете изменять код SVG, тогда вы в конечном итоге будете работать с SVG, к которому уже применены презентационные атрибуты (если вы явно не отмените это при экспорте в формат SVG) и значения этих атрибутов будут иметь приоритет над унаследованными от .
  • И даже если вы можете редактировать код SVG и можете избавиться от них, я настоятельно рекомендую этого не делать по следующим причинам:

  • Удаление атрибутов ради последующей установки определенных свойств сбросит значения этих свойств на дефолтные, а это, как правило, черная заливка и обводка (применительно к цветам).
  • Сбрасывая значения, вы вынуждаете себя задавать стили для всего набора свойств.
  • Презентационные атрибуты, которые изначально заданы, являются отличным запасным вариантом на случай возникновения проблем с внешними стилями. Если CSS не загрузится, у ваших иконок будет по-прежнему привлекательный вид.
  • Итак, у нас есть эти атрибуты, но при этом мы хотим оформить различные экземпляры иконок по разному.

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

    Давайте начнем с простых примеров и постепенно перейдем к сложным.

    Переписывание значений презентационных атрибутов с помощью CSS

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

    Это просто благодаря ключевому слову CSS inherits . Взгляните на следующий пример - иконка мороженого, нарисованная одним контуром, цвет которого мы хотим изменять в разных экземплярах. Иконка создана Эрин Агноли из Noun Project .

    Содержимое нашей иконки с мороженым (path) определено внутри элемента , а, значит, оно по умолчанию не будет выводится на холст.

    Мы выводим множественные экземпляры иконки с помощью .

    Ширину и высоту иконок мы задаем с помощью CSS. Я использую те же размеры, что и у viewBox , но они не должны быть идентичными. Однако, чтобы избежать избытка пустого пространства внутри SVG, убедитесь, что вы сохраняете соотношение между сторонами.

    Icon { width: 100px; height: 125px; }

    С этим кодом мы получили следующий результат:

    Заметьте, что благодаря добавленным черным рамкам вокруг наших SVG вы видите границы каждого из них, в том числе и первого, в котором содержимое не рендерится. Запомните: SVG-документ, в котором вы определили symbol будет выводится на страницу, но без содержимого . Чтобы предотвратить это, используйте свойство display: none на первом SVG. Если вы не спрячете SVG с определениями иконок, он будет выводится на экран даже если вы не зададите для него размеры - он займет дефолтные 300 на 150 пикселей (это значение по умолчанию для незамещаемых элементов в CSS) и вы получите ненужный вам пустой блок на экране.

    Теперь попробуем изменить цвет заливки для каждого экземпляра иконки:

    Use.ic-1 { fill: skyblue; } use.ic-2 { fill: #FDC646; }

    Цвет заливки иконок по-прежнему не меняется, так как унаследованный цвет переписывается атрибутом fill="#000" в элементе path . Чтобы это не произошло, нам надо вынудить path унаследовать цвет:

    Svg path { fill: inherit; }

    Вуаля! Цвета, заданные элементам теперь применяются к path каждого из них. Проверьте демо и поэкспериментируйте со значениями, создавая экземпляры и задавая им разные цвета:

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

    Оформление содержимого с помощью свойства CSS all

    Некоторое время назад, при работе над иконкой, активируемой с помощью , мне надо было, чтобы один из элементов внутри него унаследовал все стили , такие как fill , stroke , stroke-width , opacity и даже transform . Таким образом, мне надо было контролировать все эти атрибуты через CSS, сохраняя при этом в разметке все презентационные атрибуты в качестве запасного варианта.

    Если вы столкнетесь с похожей задачей, вы, вероятно, решите, что она займет слишком много времени, если все делать в CSS:

    Path#myPath { fill: inherit; stroke: inherit; stroke-width: inherit; transform: inherit; /* ... */ }

    Рассмотрев этот сниппет, вы заметите паттерн, а, значит, имело бы смысл объединить все указанные свойства в одно и задать ему значение inherit .

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

    Используя свойство all мы можем сделать так:

    Path#myPath { all: inherit; }

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

    Заметьте, что это относится только к атрибутам, которые можно устанавливать с помощью CSS, а не к атрибутам, задаваемым только в SVG. Если атрибут может быть задан с помощью CSS - он унаследует стили, иначе нет.

    Возможность активировать наследование презентационными атрибутами всех стилей , но что если у вас иконка, состоящая из нескольких элементов и вы не хотите, чтобы все они унаследовали один и тот же цвет заливки? Что если вы хотите применять множество различных цветов заливки для разных потомков? Задание одного стиля в уже не подходит. Нам нужно что-то другое, чтобы каскадировать нужные цвета к нужным элементам.

    Использование переменной CSS currentColor для оформления содержимого

    Использование переменной CSS currentColor в сочетании с техникой, описанной выше, позволяет определить два цвета для элемента, а не один. Год назад Фабрис Вайнберг написал об этом .

    Идея состоит в том, чтобы одновременно применять к свойства fill и color , а затем каскадировать эти свойства к содержимому , используя возможности переменной currentColor . Посмотрим на пример кода, чтобы понять, как это работает.

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

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

    Если мы зададим цвет заливки (fill) в элементе для каждого экземпляра, этот цвет будет унаследован обоими каплями, что не является нашей целью.

    Поэтому вместо определения цвета заливки и каскадирования его обычным способом, мы будем использовать переменную currentColor , чтобы меньшая капля на переднем плане была другого цвета и это значение мы зададим с помощью свойства color .

    Для начала нам надо вставить currentColor туда, где мы хотим применить этот цвет - это будет место в разметке, где определяется иконка, то есть внутри . Теперь этот фрагмент выглядит так:

    Затем нам надо удалить презентационный атрибут fill из второй капли и позволить ей унаследовать цвет заливки (fill) от элемента с помощью inherit .

    Если бы мы использовали ключевое слово inherit , чтобы вынудить презентационные атрибуты унаследовать значения от , обе части унаследовали бы одинаковое значение, а currentColor не имела бы никакого эффекта. Поэтому в этой технике нам надо удалить тот атрибут, который мы хотим задать через CSS, а оставить только тот, в котором мы будем использовать currentColor .

    Теперь, используя свойства fill и color в мы добавим стили к капле из логотипа:

    Codrops-1 { fill: #4BC0A5; color: #A4DFD1; } .codrops-2 { fill: #0099CC; color: #7FCBE5; } .codrops-3 { fill: #5F5EC0; color: #AEAFDD; }

    Каждый элемент получает собственное значение fill и color . В каждом из них цвет fill каскадируется и заполняет первый контур, не имеющий атрибута fill , а цвет свойства color используется для задания атрибута fill во втором контуре.

    Так что произошло следующее: значение текущего цвета просочилось в стили содержимого элемента за счет использования переменной currentColor . Изящно, не правда, ли?

    Вот демо с использованным кодом:

    Этот двухцветная техника отлично подходит для двухцветных лого. В своей статье Фабрис создал три различных версии лого Sass, изменяя цвет текста относительно фона.

    Ключевое слово currentColor это единственная доступная переменная CSS на данный момент. Однако, если бы у нас было бы больше переменных, могли бы мы их использовать для заполнения еще большего количества значений в содержимом ? Да, могли бы. Амелия Беллами-Ройдс год назад представила концепцию этого в своем блоге на Codepen . Посмотрим, как это работает.

    Будущее: оформление содержимого c помощью переменных CSS

    Код робота содержит все составляющие его цвета:

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

    С добавленными переменными код будет следующим:

    Так как инлайновые теги style переписывают презентационные атрибуты, браузеры с поддержкой CSS-переменных будут использовать эти переменные для задания цвета заливки (fill). А браузеры, не поддерживающие их, будут использовать атрибут fill .

    Затем нам надо задать значения для переменных в CSS. Но сначала инстанцируем изображение с помощью :

    После этого зададим значения переменных для use , чтобы они могли каскадироваться к его содержимому. Выбранные вами цвета создадут цветовую схему рисунка. Так как в нашем роботе используется три основных цвета, мы назовем их primary , secondary и tertiary .

    #robot-1 { --primary-color: #0099CC; --secondary-color: #FFDF34; --tertiary-color: #333; }

    Вы по-прежнему можете использовать свойства fill и color вместе с этими переменными, но вы можете вполне обойтись и без этого. Итак, с цветами заданными в наших переменных, робот выглядит так:

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

    Как было упомянуто, браузеры, не поддерживающие CSS-переменные используют заданные презентационные атрибуты в качестве запасного варианта, а браузеры с поддержкой переменных CSS используют их для заполнения свойства fill и переписывания атрибутов. Но что происходит, если браузер поддерживает переменные CSS, но вы забыли задать эти переменные в стилях или задали некорректное значение?

    Для нашего робота-хипстера мы задали три переменных и только несколько его фрагментов не зависят от них - ведь он изначально разрабатывался для возможной темизации. Поэтому если вы запустите этот код в браузере с поддержкой переменных CSS и удалите все декларации с объявлением этих переменных, вы получите следующий результат:

    Если значения переменных не заданы или не корректны, браузер будет использовать свой цвет по умолчанию, а это обычно черный цвет для заливки и обводки в SVG.

    Обойти это можно, задав другой цвет в качестве запасного варианта для поддерживающих браузеров. Синтаксис переменных CSS позволяет сделать так: вместо передачи функции var() имени переменной в качестве аргумента, вы передаете два аргумента, разделенных запятой - имя переменной и запасной вариант, в данном случае это будет значение для презентационного атрибута.

    Итак, теперь код нашего робота выглядит так:

    И это все. Если у какой-либо переменной не будет задано значение, у браузера всегда будет в запасе цвет, заданный в качестве запасного варианта. Замечательно.

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

    Вы можете поэкспериментировать с демо, создать сколько угодно копий робота и раскрасить его любыми цветами - не забудьте только, что для этого обязательно надо использовать браузер с поддержкой переменных CSS :

    Если вы просматриваете это демо в браузере с поддержкой переменных CSS, то среди прочих вы увидите голубую с желтым версию робота, как мы и задавали в CSS-переменных. Иначе вы увидите трех одинаковых роботов с цветом запасного варианта.

    Подводя итоги

    Это была большая статья.

    Используя возможности каскада CSS, оформление содержимого , хранимого в теневом DOM, становится менее сложным. А с переменными CSS (currentColor или с пользовательскими свойствами) мы можем проникнуть в теневой DOM и кастомизировать нашу графику, как хотим, создавая при этом запасной вариант на случай проблем.

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

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

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

    • Tutorial

    Нам нужно:

  • Установить на сайте собственные иконки с помощью SVG.
  • Они должны управляться с помощью CSS (форма, размер, заливка, эффекты в том числе и их поведение).
  • Они должны иметь маленький вес и находиться в одном месте для экономии http запросов.
  • Работать во всех основных современных браузерах.
  • демо Зачем я это пишу? Несмотря на растущую популярность вектора в браузере, его возраст и поддержку браузерами , хороших решений использования, как кажется мне, очень мало. Позвольте объясниться. Конечно о SVG много писали и рассказывали . Даже о SVG и CSS вместе. Но когда я столкнулся с необходимостью сделать SVG иконки для сайта, не смог найти хороших гибких решений. SVG в браузере сейчас выглядит всеми забытым пожилым человеком, пора его причесать, встряхнуть от пыли и отправить в спорт зал. Надеюсь описанный в этой статье метод для кого нибудь будет полезным.

    Сразу скажу да, я использовал иконочные шрифты, вот в чем здесь проблемы:
    1. Такие иконки в браузере рендерятся как шрифт и в Windows, например, часто получаются мыльные края. Есть CSS свойства , которые должны решать эту проблему, но они работают только в WebKit и только под MAC - то есть бесполезны. Дизайнер ругался.
    2. Только в 23 Chrome и только под Windows такой шрифт начал исчезать, а в некоторых случаях сильно «рвать» остальную верстку сайта. Я много раз пользовался такими шрифтами, но первый раз со своими собственными иконками. И первый раз такая проблема.
    3. Невозможно добавлять внутреннюю тень. В проекте это было обязательно. Дизайнер ругался.
    4. Вес такого шрифта. C SVG не сравнится.
    5. Все-таки SVG имеет больше возможностей по сравнению со шрифтом.

    Приступим или исходные данные. Исходные данные - чиcтый HTML документ с подключенным к нему main.css или то место, где мы будем писать стили наших иконок.
    Так же добавим SVG документ в тег body. В нем, в разделе defs, мы будем декларировать формы наших иконок в виде clip-path и фильтры для них (внутренняя тень).
    Как декларировать SVG лучше подсмотреть у вредного старичка , так как он самый превередливый.

    Добавляем форму иконки Как получить SVG код, я думаю, писать не нужно? Достаточно просто открыть SVG файл в текстовом редакторе или воспользоваться любым векторным редактором, например Illustrator. Для наглядности здесь я показываю только SVG код из нашего HTML документа (помните, что он находится в теге body). Создаем тег clipPath и добавляем в него SVG форму иконки.

    Мы создали путь для иконки в виде сердца. Прошу обратить внимание на аттрибут id="heart-path" у тега clipPath.
    Через него мы будем ссылаться на форму нашей иконки.

    Добавляем иконки Вставляем в HTML документ нашу иконку. Она состоит из маленького SVG документа, внутрь которого вставлен квадрат:


    Сразу видим небольшой недостаток подхода - иконка состоит из двух элементов. Проблема, на мой взгляд, терпимая так как структура у всех иконок абсолютно одинаковая. Если что, можно легко найти/заменить/убрать через поиск по всему проекту.

    Обратите внимание на цифру 512. Это размер квадрата в который была вписанна иконка, когда рисовалась в редакторе. С Вашей иконкой может быть иначе. Класс heart-icon для задания формы иконки в CSS, класс icon - объединяющий класс для всех иконок (их же будет масса?).

    Последний шаг. Добавляем CSS Давайте посмотрим что получилось. Если Вы все сделали правильно, то увидите черный квадрат 512 на 512 пикселя. Малевич уже одобряет. Но, боюсь, наш с вами манифест супрематизма никто уже не оценит. Продолжаем.

    Все правильно, иконок нет? Приступаем к самому интересному - CSS.

    В main.css который мы подключили к документу пишем стили для классов heart-icon и icon.

    Icon{ width:32px; height:32px; cursor:pointer; fill: #ccc; } Наш черный квадрат становится серым и 32х32 пикселя. Свойство fill задает заливку нашей иконки.

    Heart-icon rect{ clip-path:url("#heart-path"); } Наконец-то появляется форма иконки! clip-path именно то cвойcтво, которое заставляет браузер брать форму по #heart-path и применять ее к квадрату.

    Добавим поведение для иконки. Это будут:hover, :active состояния и checked класс.

    Heart-icon rect{ clip-path:url("#heart-path"); } .icon:hover{ fill: #999; } .icon:active, .icon.checked{ fill:red; }

    Добавляем внутренюю тень Для этого мы будем использовать SVG filter.
    Сразу предупреждаю. Для данного примера у меня возникали небольшие трудности с иконками при использовании фильтра поверх них. Часть из них иногда исчезала. Иногда. Может только у меня. Будьте на чеку. И еще одна проблема - чтобы фильтр накладывался красиво нужно добавить еще один элемент в иконку. Да, очень жаль. Теперь иконка с фильтром = 3 элемента. Так что если Вам нужно воплатить трендовый флет дизайн , смело .

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

    Добавляем в раздел SVG документа фильтр:

    Описывать как работает фильтр, я не стану. Вы запросто прочитаете это в интернете. Это ведь тема для отдельного поста. Просто покрою его комментариями.
    Обратите внимание что у фильтра тоже есть id="inset-shadow"

    Добавляем к иконкам тень
    .icon g{ filter:url("#inset-shadow") }
    Вот и все . Хочется мне написать. Но это было бы неправдой.

    Правда или любим всех Дело в том, что если вы откроете пример в Opera, то увидите набор из 3 квадратов. Те иконки, что с тенью и вовсе исчезают и это проблема SVG фильтров. Если браузер не находит нужный фильтр, он рендерит иконку прозрачной, вместо того, чтобы просто его не применять.

    Но почему же не находит?! Дело в том, что здесь сталкиваются 2 браузерных мира. Наш путь url("#heart-path") Opera воспринимает как путь относительный файла CSS или url("main.css#heart-path") вместо url("index.html#heart-path"), как делают это остальные. Если задать путь эксклюзивно как url("index.html#heart-path"), то браузеры не парсят SVG документ внутри index.html, так как считают его внешним источником. Такие же проблемы возникают и у Mozilla, как только Вы переносите main.css за пределы каталога с файлом index.html. IE же в этом вопросе солидарен с WebKit. А WebKit в свою очередь не очень дружит с внешними источниками. Им нужен внутренний.

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

    Итак нам нужно:

  • Два CSS файла с разными путями для двух разных миров.
  • Редактировать и поддерживать стили иконок в одном месте(файле).
  • Иметь один источник декларации форм иконок и фильтров - один SVG документ.
  • Не задумываться об этом в дальнейшем при разработке.
  • Приступим. В решении этих задач нам помогут препроцессоры. В качестве CSS препроцессора в данном примере я буду использовать Stylus , который незаслуженно обделен вниманием русскоязычного сообщества разработчиков, но максимально просто и наглядно проиллюстрирует данный пример.
    В качестве HTML препроцессора я буду использовать PHP, самый массовый препроцессор и серверный язык одновременно. Любой разработчик, пользовавшийся когда-нибудь препроцессором запросто напишет этот пример для своего любимого инструмента. Главное принцип.

    Давайте переименуем файл index.html в index.php. После этого создадим папку /css и разместим в ней файл icons.svg, куда перенесем наш большой SVG документ с декларациями форм иконок.

    На месте большого SVG документа в index.php напишем PHP выражение

    которое включает текст файла icons.svg на то место, где встречается само выражение.
    Пункт 3 выполнен, можно вычеркивать.

    Теперь пункт 1 и 2.

    В каталоге /css создадим файл icons.styl. Это будет именно то одно место, где мы будем редактировать стили наших иконок. Переместим в него все содержимое файла main.css и оформим в виде миксина icons_mixin:
    icons_mixin(path = "") .heart-icon rect{ clip-path:url(path + "#heart-path"); } .play-icon rect{ clip-path:url(path + "#play-path"); } .icon{ width:32px; height:32px; cursor:pointer; fill: #ccc; g{ filter:url(path + "#inset-shadow") } &:hover{ fill: #999; } &:active, &.checked{ fill:red; } }
    Миксин принимает в качестве параметра путь к SVG формам. Его мы будем использовать при формировании путей для разных браузеров.
    CSS стили иконок нисколько не изменились, я просто добавил нестинг для удобства и наглядности примера.

    Теперь создадим еще 2 .styl файла. webkit_ie.styl и ff_op.styl.
    Первый будем использовать на нашем вебсайте по умолчанию, второй только для Mozilla и Opera.

    В файл webkit_ie.styl добавим:
    @import "icons.styl" icons_mixin()
    Импортируем файл с миксином иконок и выполняем его без параметров.
    В файл ff_op.styl добавим:
    @import "icons.styl" icons_mixin("icons.svg")
    Импортируем файл с миксином иконок и передаем ему путь к icons.svg.

    Пункт 1 и 2 выполнены. Вычеркиваем.

    Если запутались, вот так выглядит проект:

    В index.php поправим путь к стилям иконок, теперь это

    И в самом конце, перед закрывающимся тегом добавим скрипт для условного добавления стилей иконок для браузеров с движком отличным от WebKit или Trident(IE):

    var firefox = navigator.userAgent.indexOf("Firefox") != -1 ; var opera = navigator.userAgent.indexOf("Opera") != -1 ; if (firefox || opera) { document.write(""); }
    Вот и все. исходники

    Что же мы наделали!? Давайте оглянемся назад и посмотрим, что натворили. Несмотря на то, что с первого взгляда, система может показаться слишком комплексной, мне кажется, она получилась достаточно гибкая и простая (с моего второго взгляда) чтобы иметь право на жизнь.
    • Она полностью управляется с помощью CSS.
    • Она может работать в
      • IE 9-10
      • Mozilla 4+
      • Opera 11.6+
      • Safari 5.1+
      • Chrome 14+ (я думаяю и 4+, но проверял только до этой версии)
    • Она достаточно легка по весу. (Вспомним иконку плей Вес ее составляет всего 85 байт)
    • Все иконки лежат в одном файле, так что мы не будем сервер доставать запросами.
    Все задачи выполнены. Здесь с Вашего позволения я и остановлюсь. Всем большое спасибо за внимание и время, надеюсь, Вы провели его с пользой.

    Теги: Добавить метки

    Перед тем как начать разговор о SVG анимации, давайте разберемся, что такое SVG.
    S calable V ector G raphics - масштабируемая разметка в екторной графики. Предназначена для описания двумерной векторной и смешанной векторно/растровой графики в формате XML. Позволяет задать любую фигуру компактной строкой, описывающей путь от начальной точки до конечной через любые промежуточные координаты.

    Формат SVG имеет ряд достоинств:

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

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

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

      Совместимость с таблицами стилей (CSS), которые используются для описания внешнего вида страниц сайтов.

      Анимация реализована в SVG с помощью языка SMIL. Элементами можно управлять при помощи JavaScript.

    И несколько недостатков, куда же без них:

    • Сложность использования в крупных картографических приложениях. Мелкие детали описывать слишком трудоёмко.

    • Чем больше в изображении мелких деталей, тем быстрее растёт размер SVG-данных.

    Пример SVG кода:

    Исполнение данного кода:

    В даном изображении можно просто изменить параметры в коде. Для примера - картинка с изображением занимает 35.5 КБ, а код SVG - 426 байт.

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

    Так зачем же разработчику использовать SMIL? Есть некоторые свойства SVG, которые невозможно изменить и анимировать при помощи CSS. Например, атрибут d=””, в котором находится набор данных, определяющих форму элемента. Недостающие возможности анимации на CSS можно восполнить с помощью JavaScript. Для этого есть ряд библиотек. Это будет целесообразно, если браузер (например Opera Mini) не поддерживает SMIL анимацию.

    Целевой объект анимации задается с помощью xlink:href.

    Если атрибут xlink:href не задан, то целевым элементом становится родительский элемент:

    Атрибут attributeName используется для указания имени атрибута, который будет анимироваться. К примеру, если нужно анимировать положение центра фигуры на оси Y, нужно задать “сy” в качестве значения атрибута attributeName.

    Вот код, который позволяет анимировать движение по оси Y синего круга из предыдущего примера:

    В течение 5 секунд (dur="5s"), после клика на синий круг (begin="click"), он будет двигаться по оси Y, начиная с точки from="300" в точку to="100". После выполнения - анимация остановится в конечной точке (fill="freeze"). Чтобы задать бесконечное повторение анимации, достаточно добавить атрибут repeatCount="indefinite".

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

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

    Продолжение предыдущей статьи “Стилизация SVG с помощью CSS - Часть 1”, посвященной формату векторной графики SVG.

    Стилизация с помощью CSS

    Между языками HTML и CSS существует четкая и ясная взаимосвязь: язык HTML предназначен для структуризации контента на странице; задача языка CSS - внешнее оформление этого контента . Формат SVG размывает четкие границы этой взаимосвязи. Например, формат версии SVG1.1 не нуждается в CSS для стилизации отдельных элементов SVG-объектов - для этой цели имеются так называемые презентационные атрибуты .

    Презентационные атрибуты являются сокращениями CSS-свойств для SVG-элементов. Можно думать об этих атрибутах, как о CSS-свойствах для SVG с особым синтаксисом. К этим свойствам применима каскадность стилей, но в этой статье мы поступим более кратким способом.

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

    многоугольника в виде пятиконечной звезды:

    В этом примере атрибуты

    1 fill
    , или , абсолютно не похожи на свои CSS-аналоги.

    В формате SVG2 имеются несколько презентационных атрибутов , таких как

    1 x
    ,
    1 y
    ,
    1 width
    ,
    1 height
    ,
    1 cx
    ,
    1 cy
    и некоторые другие, которые невозможно задать с помощью CSS в SVG1.1. Список новых SVG-атрибутов можно посмотреть по этой ссылке - SVG2 спецификация .

    Другим способом стилизации SVG-элементов является использование для этой цели CSS-свойств. Точно также, как и в случае в HTML-элементами, CSS-свойства могут быть заданы с помощью inline-стиля:

    Каскады стилей SVG

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

    Презентационные атрибуты позиционируются как “авторские стилевые правила” и могут быть переопределены любыми другими определениями: внешними таблицами стилей, внутренними таблицами стилей или же inline-стилями.

    Диаграмма ниже показывает порядок расположения стилей в каскаде стилей. Чем ниже расположены стили в этой таблице, тем большим количеством вышележащих стилей они могут быть перезаписаны. В нашем случае презентационные стили могут быть переопределены почти всеми другими стилями, кроме стилей агента пользователя :

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

    с помощью правила , , и . Замечания

    Так как презентационные атрибуты имеют XML-синтаксис, то они чувствительны к регистру . Например, при задании цвета заливки SVG-элемента атрибут должен быть записан как

    в ,
    1
    или внешние таблицы стилей.

    На этом все.

    Updated on March 26, 2015 gearmobile