Подробная статья об оформлении содержимого в элементе SVG
Графика в формате SVG особо часто применяется для создания иконок и одной из самых распространенных техник для этого являются SVG-спрайты с использованием SVG use для инстанцирования иконок в нужном месте документа.
Инстанцирование иконок или любого другого содержимого SVG в элементе
Но перед тем как начать, давайте быстро рассмотрим основную структуру и группирование элементов в SVG, постепенно перейдя к
Краткий обзор структуры SVG, группирования и ссылок на элементы в SVG
SVG включает в себя 4 основных элемента для определения, структурирования и создания ссылок на содержимое SVG в документе. Эти элементы дают возможность многократного использования изображений, оставляя код читаемым и поддерживаемым. Из-за природы SVG некоторые из этих элементов имеют функциональность, аналогичную соответствующим командам в графических редакторах.
4 основных группирующих и связывающих элемента SVG это
Элемент
Группирование элементов полезно в тех случаях, когда вы хотите применить стиль ко всем элементам группы, а также, когда вы хотите анимировать все элементы группы, сохранив соотношение между ними.
Элемент
Элемент
У элемента
Элемент
Чтобы использовать элемент вам надо передать ссылку на этот элемент, идентификатор - это атрибут xlink:href и спозиционировать его, задав атрибуты x и y . Вы можете применить стили к элементу
Но что является содержимым
Перед тем как ответить на эти вопросы и с учетом того, что мы только по-быстрому разобрали структуру и группирование 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. На следующем изображении показан пример элемента
Используя инструменты разработчика Chrome, вы можете инспектировать содержимое элемента use внутри теневого DOM (“#shadow-root”, строка выделена серым цветом). На этом скриншоте инспектируется логотип Codrops из примера, который мы будем рассматривать в следующем разделе.
Глядя на инспектируемый код, вы можете увидеть, что теневой DOM очень похож на обычный, за исключением того, как он обрабатывается CSS и JavaScript основного документа. Существуют также иные различия между ними, которые мы не будем рассматривать в этой статье по причине их объема, поэтому если вы хотите узнать больше, я рекомендую вам следующие статьи:
- Теневой DOM 101 (перевод на Frontender.info)
- Введение в теневой DOM (Видео)
С учетом моего ограниченного опыта взаимодействия с теневым DOM, я рассматриваю его как обычный DOM, который нужно по другому обрабатывать в части доступа CSS и JavaScript к его элементам. Это то, что важно для нас при работе с SVG: как воздействовать на содержимое
Как было сказано, содержимое теневого DOM недоступно для CSS в отличие от обычного DOM. Так как нам стилизовать его? Мы не можем использовать путь к потомкам типа такого:
Use path#line { stroke: #009966; }
Потому как у нас нет доступа к теневому DOM с помощью обычных CSS селекторов.
Возможно, вы, как и я ожидаете, что презентационные атрибуты имеют самую высокую специфичность среди всех стилевых правил. Ведь обычно внешние стили переписываются внутренними декларациями, а те в свою очередь переписываются строчными стилями атрибутов - они имеют максимальную специфичность, а, соответственно, и приоритет перед остальными стилями. И хотя это ожидание имеет смысл, действительный механизм работы отличен.
На самом деле, презентационные атрибуты рассматриваются как низкоуровневые “авторские таблицы стилей” и они переписываются остальными стилевыми декларациями: внешними, внутренними и инлайновыми стилями. Их единственная сила это приоритет перед унаследованными стилями. И все.
Теперь, когда мы выяснили это, вернемся к нашему элементу
Мы знаем, что мы не можем задать стили внутри
Но мы также знаем, что как и в случае с элементом
Итак, сначала попытаемся изменить цвет заливки (fill) элемента внутри
Однако, это вызывает пару вопросов:
- Цвет заливки будет унаследован всеми потомками
элемента
, даже теми, к которым вы не хотите применять стили (но если внутри у вас всего один элемент, то этой проблемы не будет). - Если вы экспортировали SVG из графического редактора или по каким-либо иным причинам не можете изменять код SVG, тогда вы в конечном итоге будете работать с SVG, к которому уже применены презентационные атрибуты (если вы явно не отмените это при экспорте в формат SVG) и значения этих атрибутов будут иметь приоритет над унаследованными от
.
И даже если вы можете редактировать код SVG и можете избавиться от них, я настоятельно рекомендую этого не делать по следующим причинам:
- Удаление атрибутов ради последующей установки определенных свойств сбросит значения этих свойств на дефолтные, а это, как правило, черная заливка и обводка (применительно к цветам).
- Сбрасывая значения, вы вынуждаете себя задавать стили для всего набора свойств.
- Презентационные атрибуты, которые изначально заданы, являются отличным запасным вариантом на случай возникновения проблем с внешними стилями. Если 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; }
Вуаля! Цвета, заданные элементам
Теперь эта техника работает, после того как мы вынудили содержимое
Оформление содержимого с помощью свойства CSS all
Некоторое время назад, при работе над иконкой, активируемой с помощью
Если вы столкнетесь с похожей задачей, вы, вероятно, решите, что она займет слишком много времени, если все делать в 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 в сочетании с техникой, описанной выше, позволяет определить два цвета для элемента, а не один. Год назад Фабрис Вайнберг написал об этом .
Идея состоит в том, чтобы одновременно применять к
Предположим, мы хотим оформить это минималистичное лого Codrops, используя 2 цвета - один для передней капли, а второй для задней.
Во-первых, начнем с кода для этого изображения: у нас есть symbol , содержащий описание иконки и три экземпляра
Если мы зададим цвет заливки (fill) в элементе
Поэтому вместо определения цвета заливки и каскадирования его обычным способом, мы будем использовать переменную currentColor , чтобы меньшая капля на переднем плане была другого цвета и это значение мы зададим с помощью свойства color .
Для начала нам надо вставить currentColor туда, где мы хотим применить этот цвет - это будет место в разметке, где определяется иконка, то есть внутри
Затем нам надо удалить презентационный атрибут fill из второй капли и позволить ей унаследовать цвет заливки (fill) от элемента
Если бы мы использовали ключевое слово inherit , чтобы вынудить презентационные атрибуты унаследовать значения от
Теперь, используя свойства fill и color в
Codrops-1 { fill: #4BC0A5; color: #A4DFD1; } .codrops-2 { fill: #0099CC; color: #7FCBE5; } .codrops-3 { fill: #5F5EC0; color: #AEAFDD; }
Каждый элемент
Так что произошло следующее: значение текущего цвета просочилось в стили содержимого элемента
Вот демо с использованным кодом:
Этот двухцветная техника отлично подходит для двухцветных лого. В своей статье Фабрис создал три различных версии лого Sass, изменяя цвет текста относительно фона.
Ключевое слово currentColor это единственная доступная переменная CSS на данный момент. Однако, если бы у нас было бы больше переменных, могли бы мы их использовать для заполнения еще большего количества значений в содержимом
Будущее: оформление содержимого 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, оформление содержимого
Лично мне очень симпатично сочетание переменных CSS и SVG. Мне нравятся их совместный функционал, особенно в части создания механизма запасного варианта.
Мы также можем получить другие способы оформления содержимого
Работа с многократно используемым содержимым SVG является одним из сложных вопросов SVG, это связано с поведением и местом расположения клонируемого кода. Здесь возникает очень много смежных вопросов, которые могут стать темой отдельных статей.
На этой странице показано, как использовать CSS со специальным языком для создания графики: SVG .
Вы сделаете небольшой пример, которые можно будет запустить в любом браузере с поддержкой SVG.
Общая информация: SVG
SVG (Scalable Vector Graphics) является подмножеством языка XML и предназначен для создания графики.
SVG можно использовать для статических изображений, а также для анимаций и создания пользовательских интерфейсов.
Как и прочие языки, основанные на XML, SVG поддерживает использование таблиц стилей CSS, что позволяет отделить различные варианты визуального отображения от структуры данных.
Кроме того, таблицы стилей, которые вы используете в других языках разметки документов, могут содержать ссылку на SVG графику, в тех местах, где необходимо изображение. Например, в таблице стилей, для вашего HTML документа, можно указать ссылку (URL) на SVG графику в свойстве background.
На момент написания статьи (середина 2011года), большинство современных браузеров имеет базовую поддержку SVG, в том числе Internet Explorer 9 и выше. Некоторые дополнительные возможности SVG не поддерживаются, либо поддерживаются лишь частично, в определенных браузерах. Для более подробной информации о текущей поддержке SVG, см. SVG tables on caniuse.com , либо в таблицах совместимости SVG element reference , для информации о поддержке отдельных элементов. В остальные версии можно добавть поддержку SVG, установив дополнительный плагин, например, предоставленный компанией Adobe . Более подробная информация о SVG в Mozilla, представлена на станице SVG в этой wiki. |
За дело: Демонстрация SVG
Создайте новый документ SVG, как обычный текстовый файл, doc8.svg . Скопируйте и вставьте содержимое блока ниже, убедитесь, что пролистали его полностью, чтобы скопировать все:
Создайте новый файл CSS, style8.css . копируйте и вставьте содержимое блока ниже, убедитесь, что пролистали его полностью, чтобы скопировать все:
/*** SVG demonstration ***/ /* page */ svg { background-color: beige; } #heading { font-size: 24px; font-weight: bold; } #caption { font-size: 12px; } /* flower */ #flower:hover { cursor: crosshair; } /* gradient */ #fade-stop-1 { stop-color: blue; } #fade-stop-2 { stop-color: white; } /* outer petals */ #outer-petals { opacity: .75; } #outer-petals .segment-fill { fill: azure; stroke: lightsteelblue; stroke-width: 1; } #outer-petals .segment-edge { fill: none; stroke: deepskyblue; stroke-width: 3; } #outer-petals .segment:hover > .segment-fill { fill: plum; stroke: none; } #outer-petals .segment:hover > .segment-edge { stroke: slateblue; } /* inner petals */ #inner-petals .segment-fill { fill: yellow; stroke: yellowgreen; stroke-width: 1; } #inner-petals .segment-edge { fill: none; stroke: yellowgreen; stroke-width: 9; } #inner-petals .segment:hover > .segment-fill { fill: darkseagreen; stroke: none; } #inner-petals .segment:hover > .segment-edge { stroke: green; }
Откройте документ в вашем браузере с поддержкой SVG. Переместите указатель мыши на изображение.
Эта wiki не поддерживает вставку SVG в страницы, поэтому мы не имеем возможности продемонстрировать это здесь. Изображение будет выглядеть так:
Что дальше?
В этой демонстрации, ваш браузер с поддержкой SVG уже знает, как отображать элементы SVG. Таблица стилей всего лишь некоторым образом меняет отображение. То же самое происходит с документами HTML и XUL. Однако CSS можно использовать для любых документов XML, в которых нет предусмотренного по умолчанию способа отображения элементов. Данный пример продемонстрирован на следующей странице:
SVG - формат векторной графики. Буквально его название значит «масштабируемая векторная графика» (Scalable Vector Graphics). Попросту говоря, это то, с чем вы работаете в Adobe Illustrator. SVG можно легко использовать в вебе, но сперва нужно во многом разобраться.
Зачем вообще нужен SVG?
- Небольшие размеры файлов, отличное сжатие;
- Масштабирование до любого размера, без потери качества (разве что, при совсем маленьких размерах);
- Хорошо выглядит на ретине;
- Широкие возможности, которые предоставляют фильтры и интерактивность.
Создадим изображение SVG, с которым будем работать дальше
Создайте произвольный рисунок в Adobe Illustrator. Вот, например, птица киви на овале.
Обратите внимание, что изображение кадрируется чётко по краям изображения. Холст в SVG играет не меньшую роль, чем в PNG или JPG.
Adobe Illustrator умеет сохранять в SVG.
При сохранении появится ещё одно диалоговое окно с настройками. Честно говоря, я не очень в них разбираюсь. Существует целая инструкция по Профилям SVG . Меня вполне устраивает SVG 1.1.
Здесь стоит отметить, что у вас есть возможность нажать OK и сохранить файл или же нажать кнопку “SVG Code…”, которая откроет окно TextEdit (по крайней мере на Mac) с SVG-кодом.
Оба варианта могут пригодиться.
В Illustrator рабочая область была размером 612px ✕ 502px.
Именно такие размеры будут у изображения на странице, если их не указать специально. Его размеры можно изменить, задав атрибуты width или height для img , так же как для PNG или JPG. Вот пример :
Поддержка браузерами
Один из вариантов: проверка поддержки через Modernizr и замена src для изображения:
if (!Modernizr.svg) { $(".logo img" ).attr("src" , "images/logo.png" ); }Дэвид Бушел (David Bushell) предложил очень простой альтернативный вариант , если вы не имеете ничего против JavaScript в разметке:
"this.onerror=null; this.src="image.png"" >
Для этого способа вставки SVG можно использовать следующие приемы деградации:
<svg > ... svg > <div class ="fallback" > div >И снова используем Modernizr:
.logo-fallback { display : none; /* Убедитесь, что размер соответствует размеру SVG */ } .no-svg .logo-fallback { background-image : url (logo.png); }Добавляем SVG на страницу с помощью тега
Если по какой-либо причине вариант со вставкой SVG непосредственно в документ вам не нравится (он все же имеет парочку недостатков, например, кэширование практически невозможно), можно подключить SVG-файл используя
<object type ="image/svg+xml" data ="kiwi.svg" class ="logo" > Kiwi Logo object >На тот случай, если это не поддерживается, реализуем деградацию, используя класс, который добавляет Modernizr:
.no-svg .logo { width : 200px ; height : 164px ; background-image : url (kiwi.png); }При таком подходе не возникают проблемы с кэшированием, и он поддерживается браузерами лучше , чем другие. Но если использовать внешний файл со стилями или