Магия стиля. Обводки, пунктиры и градиенты
В предыдущих уроках мы научились создавать формы и пути. Но пока они выглядят как черно-белые чертежи. В этом шаге мы вдохнем в них жизнь.
SVG обладает уникальной системой стилизации. Она похожа на обычный CSS, но свойства называются иначе. Забудьте про background-color и border — здесь они называются иначе fill (заливка) и stroke (обводка).
1. Атрибуты vs CSS
Стилизовать SVG можно двумя способами.
Способ А: Презентационные атрибуты
Вы пишете стили прямо в теге. Это надежно (работает везде, даже при сохранении картинки на диск), но замусоривает код.
<rect width="100" height="100" fill="red" stroke="black" stroke-width="5" />
Способ Б: CSS (Классы)
Самый профессиональный подход. Вы можете использовать классы, ховеры (:hover) и медиа-запросы.
<style>
.my-box {
fill: red;
stroke: black;
stroke-width: 5px;
transition: fill 0.3s;
}
.my-box:hover {
fill: blue; /* SVG поддерживает интерактивность! */
}
</style>
<rect class="my-box" width="100" height="100" />
Важно: CSS-свойства SVG специфичны.
color→ не работает (обычно). Используйтеfill.border→ не работает. Используйтеstroke.
2. Глубокое погружение в stroke (Обводка)
Обводка в SVG — это не просто цветная линия. У неё есть настройки формы концов и углов, которые критически важны для иконок и графиков.
Концы линий (stroke-linecap)
Определяет, как выглядит начало и конец разомкнутой линии.
butt(по умолчанию) — обрубленный край. Линия заканчивается ровно в точке координат.round— скругленный край. Добавляет полукруг после точки координат.square— квадратный выступ. Похож наbutt, но продлевает линию на половину её толщины.
Углы (stroke-linejoin)
Определяет, как соединяются две линии на сгибе.
miter(по умолчанию) — острый угол.round— скругленный угол (самый приятный для глаз).bevel— срезанный угол (фаска).
Пример:
<svg width="300" height="120" viewBox="0 0 300 120">
<!-- Butt + Miter (Жесткий стиль) -->
<polyline points="20,80 50,20 80,80" fill="none"
stroke="black" stroke-width="15"
stroke-linecap="butt" stroke-linejoin="miter"/>
</svg>
Вывод:
<svg width="300" height="120" viewBox="0 0 300 120">
<!-- Round + Round (Мягкий стиль) -->
<polyline points="120,80 150,20 180,80" fill="none"
stroke="crimson" stroke-width="15"
stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Вывод:
<svg width="300" height="120" viewBox="0 0 300 120">
<!-- Square + Bevel (Технический стиль) -->
<polyline points="220,80 250,20 280,80" fill="none"
stroke="steelblue" stroke-width="15"
stroke-linecap="square" stroke-linejoin="bevel"/>
</svg>
Вывод:
3. Секретная техника: stroke-dasharray
Это свойство создает пунктирную линию. Но именно на нём строится самая популярная SVG-анимация в мире — эффект "саморисующейся" линии.
Как это работает?
stroke-dasharray принимает список чисел: "длина штриха, длина пробела".
5→ штрих 5px, пробел 5px, штрих 5px...10, 5→ штрих 10px, пробел 5px...
Второе свойство — stroke-dashoffset. Оно сдвигает начало пунктира.
Трюк "Self-drawing line"
Представьте, что у вас есть линия длиной 100 пикселей.
-
Делаем штрих длиной 100px (вся линия) и пробел длиной 100px.
stroke-dasharray="100"Сейчас мы видим сплошную линию.
-
Делаем сдвиг (offset) на 100px назад.
stroke-dashoffset="100"Теперь видимая часть линии (штрих) уехала за пределы видимости, а перед нами — пустой пробел длиной 100px. Линия исчезла!
-
Если анимировать offset от 100 до 0, линия будет "выезжать" из пустоты.
Демонстрация:
<svg width="300" height="50" viewBox="0 0 300 50">
<style>
.draw-me {
fill: none;
stroke: darkorange;
stroke-width: 4;
/* 1. Задаем пунктир длиной во всю линию (допустим, 280px) */
stroke-dasharray: 280;
/* 2. Прячем линию, сдвигая пунктир */
stroke-dashoffset: 280;
/* 3. Анимация возвращает offset к 0 */
animation: draw 2s ease-in-out infinite alternate;
}
@keyframes draw {
to { stroke-dashoffset: 0; }
}
</style>
<line x1="10" y1="25" x2="290" y2="25" class="draw-me"/>
</svg>
Про анимации мы поговорим в главе 7
4. Градиенты: <defs> и <linearGradient>
В отличие от CSS, где градиент — это свойство фона (background: linear-gradient...), в SVG градиент — это отдельный объект.
Он не живет внутри фигуры. Он живет в специальном техническом разделе <defs> (Definitions) и имеет уникальный id. А фигура просто ссылается на него через url(#id).
Линейный градиент
<svg width="200" height="100" viewBox="0 0 200 100">
<!-- 1. Определяем градиент -->
<defs>
<!-- x1,y1 - начало вектора, x2,y2 - конец.
0% 0% -> 100% 0% означает градиент слева направо -->
<linearGradient id="myGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="gold" />
<stop offset="100%" stop-color="red" />
</linearGradient>
</defs>
<!-- 2. Используем его -->
<rect x="10" y="10" width="180" height="80" rx="10"
fill="url(#myGradient)" />
</svg>
Радиальный градиент
Работает так же, но используем тег <radialGradient> с атрибутами cx, cy (центр) и r (радиус).
<defs>
<radialGradient id="sunGradient" cx="50%" cy="50%" r="50%">
<stop offset="20%" stop-color="white" />
<stop offset="100%" stop-color="orange" />
</radialGradient>
</defs>
<circle cx="100" cy="50" r="40" fill="url(#sunGradient)" />
Итоговый пример: Неоновая кнопка
Объединим всё: CSS-классы, красивые обводки и градиенты.
<svg width="300" height="100" viewBox="0 0 300 100">
<defs>
<linearGradient id="neonGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#00f260" />
<stop offset="100%" stop-color="#0575E6" />
</linearGradient>
</defs>
<style>
.btn-rect {
fill: none;
stroke: url(#neonGrad);
stroke-width: 4;
stroke-linejoin: round;
/* Пунктирный эффект */
stroke-dasharray: 200 600;
stroke-dashoffset: 200;
transition: all 0.5s;
}
.btn-text {
font-family: Arial, sans-serif;
font-weight: bold;
fill: #333;
transition: fill 0.3s;
}
/* Ховер эффект: замыкаем контур и красим текст */
svg:hover .btn-rect {
stroke-dasharray: 600 0; /* Делаем линию сплошной */
stroke-dashoffset: 0;
}
svg:hover .btn-text {
fill: #0575E6;
}
</style>
<g cursor="pointer">
<!-- Прямоугольник -->
<rect class="btn-rect" x="50" y="25" width="200" height="50" rx="25" />
<!-- Текст -->
<text class="btn-text" x="150" y="55" text-anchor="middle" dominant-baseline="middle">
HOVER ME
</text>
</g>
</svg>