Анимация волны в Тильде почти всегда означает встроенный блок T536 «Обложка с изображением и волной». У него фиксированная кривая, одна волна и минимум настроек: цвет и высота, дальше вглубь не залезть. Если нужна вторая волна другого цвета, разная скорость движения по слоям или волна не в шапке, а посередине страницы под текстовым блоком, штатных инструментов Zero Block не хватает. Делаю такую анимацию через SVG и CSS-transform, без плагинов и внешних библиотек, код запускается в любом современном браузере без дополнительных зависимостей. Разберу рабочий пример, куда его вставлять в Тильде, как менять форму и скорость волны под макет и на что смотреть, если анимация тормозит на телефоне.
По теме статьи
Готовое решение
Автоматическая конвертация валюты на Tilda
Цены товаров в нужной валюте по актуальному курсу ЦБ — автоматически и в реальном времени.
от6 000 ₽
Кастомный скрипт
Когда стандартных блоков не хватает
Доработка сайтов на Тильде: скрипты для корзины, промокоды, зоны доставки, интеграции с CRM и Telegram. Простой скрипт от 3 000
от3 000 ₽
Как устроена волновая анимация: SVG плюс CSS-transform
Волна на сайте почти всегда решает одну задачу: смягчить жёсткую границу между двумя блоками разного цвета, обложкой и текстовым разделом, например. Плоская линия режет страницу, а волна размывает переход и добавляет лендингу динамики без видео и тяжёлых анимаций на JavaScript.
Технически волна - это path в SVG, а не картинка и не GIF. Кривую рисуют координатами в атрибуте d через кубические кривые Безье: у каждой точки есть две опорные ручки, которые задают изгиб линии между соседними узлами. Чем дальше ручка от точки, тем круче загиб волны.
Движение задают не через JavaScript и не через покадровое изменение самого path, это дорого для браузера и просаживает частоту кадров, а через сдвиг всего SVG-блока transform: translateX. Оборачиваю волну в контейнер шириной 200% от экрана, кладу внутрь две одинаковые SVG-копии рядом и анимирую весь контейнер от translateX(0) до translateX(-50%) в бесконечном цикле. Пока первая копия уезжает влево, под неё ровно встаёт вторая, шва не видно, и волна выглядит бесконечной лентой.
Похожий принцип использует и T536, только Тильда прячет разметку внутри своего движка и не даёт менять форму кривой напрямую, а сама волна в этом блоке статична, без движения. Через кастомный HTML-блок доступ к path открыт полностью: рисую любую форму в Figma или Illustrator, экспортирую координаты в SVG и вставляю их в код без правок вручную.
Куда вставлять код: HTML-блок или общий код сайта
HTML-блок на конкретной странице
- Добавляю на страницу пустой блок T123 «HTML-код» из категории Zero Block.
- Открываю настройки блока и вставляю в поле кода разметку SVG вместе со стилями.
- Проверяю адаптив вручную: у T123 нет автоматической мобильной версии, высоту и viewBox подгоняю под ширину контейнера через clamp().
- Смотрю результат в режиме предпросмотра, а не в редакторе: Zero Block иногда отрисовывает SVG некорректно прямо внутри конструктора, хотя на опубликованной странице всё нормально.
Этот способ подходит, если волна нужна на одной-двух страницах и её форма привязана к конкретному макету.
Код для всего сайта, если волна нужна на нескольких страницах
Если волна повторяется на лендинге и в паре разделов блога, разметку выношу в общий блок и подключаю через Настройки сайта, ещё, Код для вставки, в секцию перед закрывающим тегом body. CSS-анимация тогда не дублируется в каждом HTML-блоке и не раздувает вес страницы: на десяти страницах с одинаковой волной экономия в разметке доходит до 15-20 КБ, а для мобильного трафика Тильды это ощутимо. Минус подхода: код грузится на всех страницах сайта разом, даже там, где волна не нужна, поэтому оборачиваю вставку в проверку класса тела страницы.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Код: рабочий пример волны на SVG
Разметка для блока T123:
<div class="wave-wrap">
<svg class="wave-svg" viewBox="0 0 2400 200" preserveAspectRatio="none">
<path class="wave-path" d="M0,100 C300,180 600,20 900,100 C1200,180 1500,20 1800,100 C2000,160 2200,60 2400,100 L2400,200 L0,200 Z" fill="#2f80ed"></path>
</svg>
<svg class="wave-svg" viewBox="0 0 2400 200" preserveAspectRatio="none">
<path class="wave-path" d="M0,100 C300,180 600,20 900,100 C1200,180 1500,20 1800,100 C2000,160 2200,60 2400,100 L2400,200 L0,200 Z" fill="#2f80ed"></path>
</svg>
</div>
Стили к разметке:
.wave-wrap {
position: relative;
display: flex;
width: 200%;
height: clamp(60px, 12vw, 160px);
overflow: hidden;
animation: wave-move 9s linear infinite;
will-change: transform;
}
.wave-svg {
width: 50%;
height: 100%;
flex-shrink: 0;
}
@keyframes wave-move {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
.wave-wrap { animation: none; }
}
Path описывает одну волну шириной 2400px, вторая svg-копия - точная дублирующая её форма, нужна только для бесшовного цикла при сдвиге. Анимирую не path, а весь контейнер wave-wrap: браузер выносит такую анимацию на отдельный композитный слой и обрабатывает её GPU, а не основной поток рендера, где считается вёрстка и обрабатываются скрипты страницы. Медиа-запрос prefers-reduced-motion отключает анимацию для пользователей, которые в настройках операционной системы попросили уменьшить движение на экране, это не факультативная деталь, а реальный сценарий доступности.
Настройка скорости, высоты и цвета волны
Скорость. Меняю значение длительности в анимации wave-move: меньше пяти секунд волна выглядит нервной и отвлекает от текста, больше пятнадцати - почти незаметной. На спокойных лендингах, страховые компании и медицинские клиники, ставлю 10-12 секунд с линейным таймингом, на динамичных продуктовых страницах - 5-6 секунд, иногда с ease-in-out для более живого движения.
Высота. Завязываю через clamp на границы 60px и 160px в контейнере волны, чтобы на мобильном волна не превращалась в узкую полоску и не съедала треть экрана на маленьких дисплеях.
Цвет. Простая заливка - атрибут fill у path. Для градиента добавляю в svg блок defs с linearGradient и меняю сплошную заливку на ссылку на градиент, получается переход от основного цвета блока к акцентному без лишних слоёв в разметке. Для эффекта параллакса накладываю две-три волны друг на друга через абсолютное позиционирование, каждой задаю свою прозрачность и свою длительность анимации: слои движутся с разной скоростью, и волна выглядит объёмной, а не плоской.
Типичные проблемы: тормозит на мобильных и дёргается при скролле
Чаще всего анимация проседает по трём причинам.
Меняют path вместо transform. Пересчёт координат кривой на каждый кадр - это перерисовка геометрии, браузер не успевает уложиться в 16 миллисекунд на кадр, и волна дёргается рывками вместо плавного движения. Трансляция того же контейнера обрабатывается композитором отдельно от основного потока и почти всегда идёт ровно, даже на бюджетных смартфонах.
Слишком много слоёв волны на одной странице. Три-четыре SVG с активной CSS-анимацией одновременно - предел для среднего смартфона, особенно если рядом на странице уже крутится карусель отзывов или видео-фон. Проверяю через троттлинг процессора в Chrome DevTools: если частота кадров падает ниже 30, убираю один слой волны или увеличиваю его прозрачность до едва заметной, чтобы не грузить рендер зря.
Конфликт с адресной строкой iOS Safari. Волна на фиксированной подложке в шапке при скролле иногда дёргается из-за того, что Safari прячет и показывает адресную строку, меняя высоту viewport на лету. Тестирую именно на устройстве, а не в эмуляторе Chrome, там этот баг чаще всего не воспроизводится, и разработчик видит идеальную картинку до самой публикации.
Если волна ведёт себя нестабильно вместе со сторонним скриптом Тильды, лениво подгружаемыми блоками, парсером каталога или калькулятором на странице, проще сразу заказать доработку скрипта под конкретный Zero Block, чем перебирать причины вслепую по одной и терять на этом время.
Сравнение: доработать T536 или собрать анимацию с нуля
Если волна нужна разово в шапке лендинга и устраивает стандартная кривая, штатный блок закрывает задачу за пару минут. Кастомный скрипт оправдан, когда нужна анимация, несколько слоёв, произвольное место на странице или форма волны под фирменный стиль заказчика.
| Критерий | Блок T536 | Кастомный SVG-скрипт |
|---|---|---|
| Форма волны | Фиксированная кривая из галереи Тильды | Произвольная форма под макет |
| Анимация движения | Нет, волна статична | Бесконечный цикл с настраиваемой скоростью |
| Число слоёв | Один | Любое количество, включая параллакс |
| Место на странице | Только верхняя обложка | Любой блок страницы |
| Время на реализацию | Две-три минуты в редакторе | От получаса и больше в зависимости от числа слоёв |
Простую волну как разовую правку оцениваю от 3 000 ₽, комплексную анимацию из нескольких слоёв с адаптивом под три брейкпоинта - от 40 000 ₽, это уже полноценная интеграция в структуру страницы, а не точечная вставка кода в один блок.
Частые вопросы
Можно ли сделать несколько волн разной скорости и цвета одновременно?
Да, накладываю слои друг на друга через абсолютное позиционирование с разным z‑index, каждому слою задаю свою длительность анимации и прозрачность. Получается эффект параллакса, похожий приём часто встречается на лендингах морской и туристической тематики, где нужно ощущение глубины.
Почему волна дёргается на телефоне, хотя на компьютере всё плавно?
Обычно причина в том, что анимируется атрибут path, а не transform, либо на странице одновременно работает больше трёх SVG-слоёв с активной анимацией. Проверяю в Chrome DevTools с троттлингом процессора и сокращаю число активных слоёв до двух, этого почти всегда хватает для плавной картинки.
Как заменить встроенный блок T536 на свою анимацию без потери адаптива?
Оставляю обёртку T536, она уже адаптирована под брейкпоинты Тильды, только отключаю встроенную волну в настройках блока и накладываю свой SVG внутрь через HTML-блок с абсолютным позиционированием у нижнего края обёртки, чтобы сохранить исходную структуру блока.
Нужно ли переделывать анимацию после обновлений Zero Block?
Нет. CSS-анимация и SVG внутри HTML-блока T123 не зависят от версии движка Zero Block, они выполняются браузером напрямую и ломаются редко, разве что при ручной переверстке самой страницы менеджером сайта.