SVG-градиенты
- Содержание:
- Управление цветами
- Линейный градиент
- Радиальный градиент
- Общие свойства градиентов
- gradientUnits
- gradientTransform
- spreadMethod
- xlink:href
- Подводные камни
- Примеры использования
В SVG не работают привычные CSS-фоны, для заливок здесь есть свои конструкции: для градиентов это элементы linearGradient
и radialGradient
— линейный и радиальный градиенты соответственно.
Спецификация: w3.org/TR/SVG/pservers.html#Gradients
CSS-градиенты объявляются прямо в CSS-коде, и код самого градиента потом нельзя переиспользовать. SVG-градиенты устроены иначе: перед использованием градиент должен быть описан с помощью соответствующего тега, и после этого его можно переиспользовать сколько угодно раз. И даже больше: градиенты могут наследовать свойства друг друга (об этом будет рассказано ниже).
Код самого простого градиента выглядит вот так:
Обязательный атрибут любого градиента — id
.
Градиент не отображается на странице, пока не будет применён к элементу. Так же, как и обычная заливка или обводка, градиент задаётся с помощью fill
или stroke
— атрибутом элемента или через CSS.
Применим градиент к фигуре:
В действии:
Градиент можно использовать и как заливку и как обводку для фигур и для текста:
See the Pen NAZgqo by yoksel (@yoksel) on CodePen.
Управление цветами
Для управлениям цветами градиента служит элемент stop
. Атрибуты:
offset
— положение цветаstop-color
— цветstop-opacity
— прозрачность цвета
Пример кода:
Положение цвета задаётся в процентах или числом от 0 до 1 (50% и .5 будут работать одинаково). Цвет и положение цвета указывать обязательно.
Интересно, что в отличие от CSS-градиентов, цвета SVG-градиентов можно анимировать (в данном случае, с помощью CSS):
See the Pen Animated SVG-gradient by yoksel (@yoksel) on CodePen.
Линейный и радиальный градиенты имеют несколько общих свойств, но различаются способами, которыми задаются размер и направление градиента. Рассмотрим их поподробнее.
Линейный градиент
Задаётся с помощью тэга linearGradient
.
Вектор градиента задаётся с помощью атрибутов x1
, y1
, x2
и y2
.
x1
и y1
задают координаты начала вектора, x2
и y2
— координаты конца (похоже на рисование линии с помощью тега line
).
See the Pen Gradient Coords: x2 & y2 by yoksel (@yoksel) on CodePen.
Если координаты не заданы, рисуется горизонтальный градиент слева направо.
Кнопки вверху демо переключают свойство gradientUnits
, отвечающее за систему координат, подробнее о нём будет рассказано ниже.
Радиальный градиент
Задаётся с помощью тега radialGradient
.
Параметры градиента задаются с помощью тех же атрибутов, что определяют свойства круга (элемента circle
): центр фигуры задаётся атрибутами cx
и cy
, а радиус — атрибутом r
:
See the Pen Gradient Coords: r by yoksel (@yoksel) on CodePen.
Если какой-то из этих атрибутов не задан, ему присвоится значение по умолчанию, равное 50%
.
Помимо этого, у радиального градиента есть пара специфических свойств: fx
и fy
. Они позволяют сдвинуть только центр градиента, не затрагивая расположение конечных цветов:
See the Pen Gradient Coords: fx & fy by yoksel (@yoksel) on CodePen.
Если эти атрибуты не заданы, их значения по умолчанию будут равны cx
и cy
соответственно.
Общие свойства градиентов
gradientUnits
Это очень важное свойство, оно задаёт систему координат для атрибутов, отвечающих за направление и размеры градиента (x1
, y1
, x2
и y2
для линейных градиентов и cx
, cy
, r
, fx
и fy
для радиальных).
Возможные значения:
objectBoundingBox
— координаты рассчитываются относительно объекта, к которому применяется градиент. Значение по умолчанию.
userSpaceOnUse
— координаты рассчитываются относительно системы координат всего SVG-элемента.
Помимо того, что при переключении gradientUnits
градиент может менять своё положение из-за смены системы координат, это свойство также может существенно влиять на отрисовку градиента для фигур с разными шириной и высотой (например, вытянутый прямоугольник или эллипс).
При значении userSpaceOnUse
цвета линейного градиента всегда будут перпендикулярны основному вектору, а радиальный градиент будет иметь форму круга. Но если градиент задан вытянутой фигуре, а значение gradientUnits
равно objectBoundingBox
, градиент пытается уместиться в фигуру целиком и подвергается искажениям. Особенно это заметно на радиальных градиентах:
See the Pen gradientUnits (radialGradient) by yoksel (@yoksel) on CodePen.
У линейных градиентов в этом случае меняется угол расположения цветов градиента относительно его вектора:
See the Pen gradientUnits by yoksel (@yoksel) on CodePen.
Так что даже если системы координат фигуры и SVG-элемента совпадают, из-за разных значений gradientUnits
градиент может выглядеть по-разному.
gradientTransform
Атрибут позволяет задать трансформациии градиента:
See the Pen gradientTransform by yoksel (@yoksel) on CodePen.
Трансформации те же, что и для обычных фигур, например, градиент можно повернуть или растянуть, но в трансформациях градиентов есть некоторые подводные камни.
Для градиентов, как и для всех прочих элементов, по умолчанию трансформации производятся относительно верхнего левого угла документа. Если требуется переопределить центр трансформации, нужно задать transform-origin
. Явно в атрибуте его можно задать только для rotate
(например, rotate(180, 100, 100)
, два последних числа — это оно), для других трансформаций transform-origin
будет работать только если он вместе с трансформацией задан в CSS. Но gradientTransform
нельзя задать через CSS, следовательно transform-origin
так тоже задать не получится. В этом случае можно использовать центрирование через translate
(за подсказку спасибо @AmeliasBrain):
В случае с радиальным градиентом вместо scale
будет удобнее управлять радиусом градиента.
spreadMethod
Этот атритбут управляет поведением градиента, если градиент меньше, чем область отрисовки.
Возможные значения:
pad
— свободное пространство заполняется крайними цветами. Значение по умолчанию.
reflect
— градиент отражается.
repeat
— градиент повторяется.
See the Pen SpreadMethods for SVG Gradients by yoksel (@yoksel) on CodePen.
spreadMethod
не работает в Safari. Если надо чтобы везде работало, линейные повторяющиеся и отражённые градиенты можно имитировать с помощью паттернов, а повторение радиальных всё-таки придётся прописывать руками.
xlink:href
Этот атрибут позволяет градиентам заимствовать друг у друга цвета и свойства. Если в градиенте, содержащем атрибут xlink:href
, не заданы цвета, они унаследуются из градиента по ссылке. Также из заданного градиента унаследуются все свойства, которые не переопределены в текущем градиенте. При этом радиальные градиенты могут наследовать цвета и свойства линейного, и наоборот.
Вот пример использования:
Код в действии, радиальный градиент справа унаследовал цвета линейного градиента слева:
See the Pen Gradient properties inheritance by yoksel (@yoksel) on CodePen.
В этом демо к градиенту слева применяется трансформация, и она также наследуется градиентом справа.
Подводные камни
Градиент можно использовать в качестве заливки и обводки, и задавать его можно как атрибутами fill
и stroke
, так и в CSS. При этом можно сложить градиенты в отдельный файл, и подключать их оттуда, это избавит от необходимости вставлять градиенты в тело документа.
К сожалению, все самые удобные и интересные способы не очень хорошо поддерживаются браузерами. Так, в CSS запись вида fill: url(#grad);
подразумевает, что градиент с таким ID нужно искать в текущем документе. В Хроме, Опере и Сафари всё так и происходит, однако Firefox начинает искать градиент относительно расположения файла со стилями, и ожидаемо ничего не находит. Можно привести ссылку в CSS в соответствие с адресом страницы, но это не поможет, если страниц больше одной.
Запись вроде fill: url(svg-with-gradients.svg#gradient);
указывает, что градиент нужно брать из внешнего файла, и это было бы суперудобно, но, к сожалению, работает только в Firefox.
Таким образом, самый надёжный способ — это задавать градиент используя атрибуты элемента.
Примеры использования
SVG-градиенты сами по себе дают интересные возможности оформления, но ещё интереснее то, как они работают в сочетании с масками. Например, используя маски и градиенты можно сделать вот такие мыльные пузыри:
See the Pen SVG Bubbles by yoksel (@yoksel) on CodePen.
Тут есть подробная схема отдельного пузыря.
Также анимируя градиенты можно делать разные интересные штуки. Например, вот такой паттерн (цвета анимируются с помощью CSS):
See the Pen Animated pattern with SVG gradient by yoksel (@yoksel) on CodePen.
Или переливающийся текст:
See the Pen Text with gradientTransform by yoksel (@yoksel) on CodePen.
Анимацию цветов можно сделать с помощью CSS, трансформации можно добавить только с помощью JavaScript (я это делаю с помощью библиотеки GSAP).