Кнопка тильда почти всегда начинается с одной и той же задачи: стандартный вид блока клиента не устраивает, а менять весь блок ради одной детали не хочется. На практике с этим сталкиваюсь на каждом втором проекте на Tilda - нужен другой радиус скругления, свой hover-эффект, реакция на клик, которой в конструкторе нет по умолчанию, или кнопка, которая должна вести себя по-разному на разных страницах одного сайта. Ниже разбираю, как прицепить свои стили к кнопке, задать её состояния и повесить обработчик клика так, чтобы это не слетело при следующей правке блока.
По теме статьи
Готовое решение
Ограничение применения промокода в корзине Tilda
Промокод в Tilda не действует на выбранную категорию (например, «Распродажа»). Готовый скрипт + инструкция по подключению.
от6 000 ₽
Кастомный скрипт
Когда стандартных блоков не хватает
Доработка сайтов на Тильде: скрипты для корзины, промокоды, зоны доставки, интеграции с CRM и Telegram. Простой скрипт от 3 000
от3 000 ₽
Зачем переопределять стандартную кнопку в Tilda
Панель настроек блока закрывает базовые сценарии: цвет фона, цвет текста, радиус, размер шрифта меняются без единой строчки кода. Для лендинга с типовым дизайном этого хватает, и я всегда советую сначала проверить панель блока, прежде чем лезть в код - половина запросов «сделайте кнопку другой» решается там за пару минут.
Проблема начинается, когда нужно что-то за пределами панели: градиент вместо заливки, анимация иконки внутри кнопки, состояние «уже отправлено» после клика по кнопке в форме, отдельная логика для мобильной версии. Тут штатных полей не хватает, и приходится добавлять свой CSS-класс и код.
Второй частый повод - интеграция. Кнопка должна не просто вести по ссылке, а запускать сценарий: открывать кастомный попап с расчётом стоимости, дергать вебхук перед переходом, менять текст в зависимости от выбора пользователя на странице. Это уже не про дизайн, а про поведение, и решается через JavaScript поверх верстки, которую отдаёт Tilda. На одном из проектов кнопка «Рассчитать доставку» на карточке товара должна была сначала дернуть свой обработчик и только потом, если расчёт прошёл, открывать попап с формой заказа - без своего кода такую цепочку в конструкторе не собрать.
Где искать класс кнопки и как его зацепить
Проще всего открыть страницу в браузере, кликнуть правой кнопкой по нужному элементу и выбрать «Просмотреть код» - в инструментах разработчика сразу видно, какие классы навешаны на кнопку и какой блок за неё отвечает.
У кнопки в Tilda почти всегда есть базовый класс t-btn, плюс служебный класс конкретного блока вроде t756__btn, а у кнопки отправки формы это t-submit. Писать CSS сразу по этим классам рискованно: при смене скина блока или обновлении верстки блока Tilda эти классы могут поменяться, и стиль слетит при следующей правке страницы, о которой вы можете даже не узнать.
Практичнее добавить кнопке собственный класс и вешать стили уже на него:
- в блоке Zero Block у каждого элемента, включая кнопку, есть поле Class в настройках - туда вписывается произвольное имя, например
my-btn-primary; - в обычных блоках такого поля у кнопки нет, но можно задать ID блоку в настройках блока и писать CSS через этот ID как через дополнительный селектор;
- для HTML-блока T123 класс просто прописывается в разметке, которую вы сами вставляете.
Три способа закрывают разные ситуации, и выбор зависит от того, где физически стоит кнопка на странице.
| Способ | Где встречается | Когда использовать |
|---|---|---|
| Поле Class в Zero Block | Блоки на конструкторе Zero Block | Нужен свой стиль конкретному элементу без правки чужой верстки |
| ID блока + CSS в head | Стандартные блоки (T123, T450, T‑form и другие) | Нужно перекрыть стиль внутри блока, у которого нет своего поля класса |
| Верстка в HTML-блоке T123 | Полностью кастомная секция | Кнопка не встроена в готовый блок, а верстается с нуля |
CSS в любом из вариантов вставляется через настройки страницы: «Ещё» - «Вставить код в head» на уровне страницы или всего сайта, если стиль должен работать везде.
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Свои стили кнопки через CSS
Когда класс на кнопке есть, стиль пишется как обычный CSS, только с чуть более высокой специфичностью, чем у исходных стилей блока, иначе Tilda-стили пересилят ваши:
.my-btn-primary {
background: linear-gradient(135deg, #2f6feb, #1b4fb8);
border-radius: 10px;
padding: 14px 32px;
font-weight: 600;
transition: transform .15s ease, box-shadow .15s ease;
box-shadow: 0 4px 14px rgba(27, 79, 184, .25);
}
.my-btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(27, 79, 184, .35);
}
Форма и анимация без прыжков верстки
Анимацию завязываю на transform и box-shadow, а не на изменение padding или font-size по hover - от них соседние элементы блока дёргаются, потому что меняется реальный размер кнопки. Тень и сдвиг на пару пикселей визуально работают так же выразительно, но не ломают раскладку.
Отдельно учитываю, что на телефонах и планшетах события hover фактически нет - палец не «наводит», а сразу нажимает. Если весь эффект кнопки завязан только на hover, на мобильных он просто не увидится, поэтому важные визуальные подсказки дублирую через состояние active, которое срабатывает и на тач-устройствах тоже.
Состояния кнопки: hover, active, disabled, загрузка
У кнопки в Tilda обычно нет нативного атрибута disabled, потому что рендерится она как ссылка <a>, а не как <button> - исключение - кнопка отправки формы, она честный <button type="submit">. Поэтому состояние «недоступна» делаю через класс и pointer-events, а не через атрибут:
.my-btn-primary.is-disabled {
opacity: .5;
pointer-events: none;
box-shadow: none;
}
.my-btn-primary.is-loading {
position: relative;
color: transparent;
}
.my-btn-primary.is-loading::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 16px;
height: 16px;
margin: -8px 0 0 -8px;
border: 2px solid #fff;
border-top-color: transparent;
border-radius: 50%;
animation: btn-spin .6s linear infinite;
}
@keyframes btn-spin {
to { transform: rotate(360deg); }
}
Дальше классы is-disabled и is-loading навешиваются и снимаются уже из JavaScript в момент клика и после ответа сервера. Такой подход одинаково работает и для кнопки-ссылки, и для кнопки формы, и не требует разного кода под разные типы блоков.
Обработка клика: свой JavaScript без слома виджета
Код, который трогает кнопку, запускаю не сразу в head, а после того как Tilda отрисовала блоки на странице. Для этого использую обёртку t_onReady, которую Tilda сама подключает на страницах сайта - она гарантирует, что скрипт отработает после инициализации блоков, а не до того, как кнопка появилась в DOM:
t_onReady(function () {
var btn = document.querySelector('.my-btn-primary');
if (!btn) return;
btn.addEventListener('click', function (e) {
if (btn.classList.contains('is-disabled')) {
e.preventDefault();
return;
}
btn.classList.add('is-loading');
fetch('/api/lead', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ source: 'landing-btn' })
}).finally(function () {
btn.classList.remove('is-loading');
});
});
});
Если кнопка ставится через Zero Block, у неё в настройках есть отдельный тип действия «JS-событие»: вписываете произвольное имя события, и по клику Tilda не переходит по ссылке, а генерирует это событие в браузере. Ловится оно обычным addEventListener на document, без необходимости искать элемент кнопки руками и без риска, что при переносе блока на другую страницу селектор перестанет находить кнопку:
document.addEventListener('openCalcPopup', function () {
document.querySelector('.calc-popup').classList.add('is-open');
});
Такой вариант удобен, когда кнопок с одинаковым сценарием несколько на странице и городить отдельный класс на каждую не хочется - одно событие ловится одним обработчиком сразу для всех.
Кнопка отправки формы: валидация перед сабмитом
С кнопкой формы отдельная история: перед тем как форма Tilda уйдёт на отправку, часто нужно проверить что-то своё - например, что выбран способ доставки или отмечен чекбокс с промокодом. Вешаю обработчик на сам submit-клик и в нужных случаях останавливаю его через preventDefault, до того как сработает штатная отправка формы:
t_onReady(function () {
var submitBtn = document.querySelector('.t-submit');
if (!submitBtn) return;
submitBtn.addEventListener('click', function (e) {
var delivery = document.querySelector('input[name="delivery"]:checked');
if (!delivery) {
e.preventDefault();
e.stopImmediatePropagation();
alert('Выберите способ доставки');
}
}, true);
});
Третий параметр true у addEventListener важен: он ставит обработчик на фазу перехвата, и он срабатывает раньше внутреннего обработчика Tilda, поэтому stopImmediatePropagation реально успевает остановить отправку. Без этого параметра обработчики выполнятся в обратном порядке, и своя проверка сработает уже после того, как форма ушла на сервер.
Для аналитики по кнопке отдельный код обычно не нужен, но полей «цель Яндекс.Метрики» и «событие Google Analytics» в настройках блока нет. Есть галочка «Отправлять данные о клике в систему аналитики»: после её включения ниже появляется адрес виртуальной страницы, просмотр которой и означает клик по кнопке. Этот адрес подставляется в цель Метрики типа «Посещение страниц» в поле «url:содержит». У кнопки в Zero Block то же самое делается через Settings и поле Click tracking со значением Send data to analytics. Свой JS для трекинга имеет смысл, только если нужно передать в аналитику что-то нестандартное, например сумму заказа или выбранный тариф.
Когда сценарий на кнопке или форме выходит за рамки CSS и десятка строк JS, например, кнопка должна проверять остаток товара на складе перед отправкой заказа или дергать CRM с разными полями в зависимости от выбора пользователя, обычно проще сразу отдать кастомную доработку кнопок и скриптов для Tilda в работу, чем собирать логику из чужих примеров с форумов. Простая правка стилей и состояний укладывается в разработку от 3 000 ₽, а сценарий с интеграцией стороннего сервиса или CRM обычно оценивается как комплексная доработка от 40 000 ₽.
Условия и возможности Тильды меняются, поэтому перед запуском я уточняю их у самого сервиса.
Частые вопросы
Можно ли поменять вид кнопки без кода, только через панель Tilda
Да, цвет, размер шрифта, радиус скругления и отступы у большинства блоков меняются прямо в панели настроек блока. Код нужен, когда требуется эффект за пределами этих полей: градиент, своя анимация при наведении, состояние disabled или loading.
Почему свой CSS для кнопки не применяется на сайте
Обычно причина в специфичности селектора: собственный класс должен быть написан так, чтобы перебивать исходные стили блока, иначе побеждают классы самой Tilda. Вторая частая причина - код вставлен в head конкретной страницы, а кнопка находится на другой странице сайта, где этот код не подключен, либо сохранился старый файл в кэше браузера.
Как не дать пользователю кликнуть по кнопке дважды подряд
Добавляю класс вроде is-loading сразу в обработчике клика и снимаю его после ответа сервера, а сам клик по кнопке с этим классом блокирую через pointer-events: none в CSS или проверку класса в начале обработчика. Это защищает от повторной отправки формы или двойного вызова вебхука.
Как передать клик по кнопке в Яндекс.Метрику или Google Analytics
Отдельных полей для цели Метрики и события GA у блока нет. В настройках блока с кнопкой включается галочка «Отправлять данные о клике в систему аналитики», Тильда начинает отдавать виртуальную страницу клика, и на её адрес в Метрике создаётся цель типа «Посещение страниц» с условием «url:содержит». В Zero Block аналог этой галочки это поле Click tracking со значением Send data to analytics. Свой обработчик клика нужен только под нестандартный сценарий, который так не описывается.