Разработка кастомных блоков Tilda (Zero Block)
Zero Block — встроенный HTML/CSS/JS редактор в Tilda, позволяющий создавать секции страниц с полным контролем над разметкой и логикой. Это мост между no-code конструктором и разработкой: дизайнер или разработчик верстает произвольную секцию, которая встраивается в Tilda-страницу наравне со стандартными блоками.
Что такое Zero Block технически
Каждый Zero Block — изолированный HTML-блок с инлайн-стилями и скриптами. Tilda оборачивает его в контейнер с уникальным ID и встраивает на страницу. Переменные дизайна сайта (шрифты, цвета) доступны через CSS-переменные, которые Tilda задаёт глобально.
Ограничения изоляции:
- нет доступа к глобальному
window.TildaAPI из Zero Block напрямую (только черезwindow.addEventListener) - стили Zero Block не конфликтуют с остальной страницей (если написаны с BEM или уникальным префиксом)
- JS выполняется в глобальном контексте страницы — конфликты возможны
Редактор Zero Block
Интерфейс редактора: cold canvas с drag-and-drop элементов (прямоугольники, тексты, изображения, кнопки) + панель стилей + вкладка «HTML/CSS/JS» для кода.
Визуальный редактор генерирует стили как inline CSS на каждом элементе. Для сложной разметки — вкладка «HTML» позволяет написать разметку вручную.
Responsive breakpoints в Zero Block: Desktop (960px+), Tablet (640–960px), Mobile (< 640px). Для каждого breakpoint — отдельный набор позиций и размеров элементов.
Кастомная разметка через вкладку HTML
Для секций, которые нельзя сверстать через визуальный редактор:
<!-- Zero Block HTML tab -->
<div class="zb-pricing">
<div class="zb-pricing__header">
<h2 class="zb-pricing__title">Выберите тариф</h2>
<p class="zb-pricing__subtitle">Все тарифы включают 30 дней поддержки</p>
</div>
<div class="zb-pricing__grid">
<div class="zb-pricing__card zb-pricing__card--featured">
<div class="zb-pricing__badge">Популярный</div>
<h3 class="zb-pricing__plan">Professional</h3>
<div class="zb-pricing__price">
<span class="zb-pricing__amount">990</span>
<span class="zb-pricing__currency">₽/мес</span>
</div>
<ul class="zb-pricing__features">
<li>До 10 проектов</li>
<li>API-доступ</li>
<li>Приоритетная поддержка</li>
</ul>
<button class="zb-pricing__cta" data-plan="professional">Начать</button>
</div>
<!-- другие карточки -->
</div>
</div>
/* Zero Block CSS tab */
.zb-pricing {
max-width: 1200px;
margin: 0 auto;
padding: 60px 24px;
}
.zb-pricing__grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
margin-top: 48px;
}
.zb-pricing__card {
background: #fff;
border: 1px solid #E5E7EB;
border-radius: 12px;
padding: 32px;
transition: box-shadow 0.2s ease;
}
.zb-pricing__card:hover {
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
.zb-pricing__card--featured {
border-color: #3B82F6;
position: relative;
}
.zb-pricing__badge {
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
background: #3B82F6;
color: #fff;
font-size: 12px;
font-weight: 600;
padding: 4px 16px;
border-radius: 100px;
}
.zb-pricing__amount {
font-size: 48px;
font-weight: 700;
line-height: 1;
}
@media (max-width: 768px) {
.zb-pricing__grid {
grid-template-columns: 1fr;
}
}
Интерактивность через JavaScript
// Zero Block JS tab
(function() {
// IIFE для изоляции от глобального контекста
const cards = document.querySelectorAll('.zb-pricing__cta');
cards.forEach(btn => {
btn.addEventListener('click', function() {
const plan = this.dataset.plan;
// Открытие формы Tilda
const formBlock = document.getElementById('rec123456789');
if (formBlock) {
formBlock.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// Заполнение скрытого поля формы выбранным тарифом
const planField = document.querySelector('input[name="plan"]');
if (planField) planField.value = plan;
// Аналитика
if (window.gtag) {
gtag('event', 'select_plan', { plan_name: plan });
}
if (window.ym) {
ym(COUNTER_ID, 'reachGoal', 'PLAN_SELECTED', { plan });
}
});
});
})();
Анимации в Zero Block
Анимации при скролле через Intersection Observer:
(function() {
const cards = document.querySelectorAll('.zb-pricing__card');
// Начальное состояние
cards.forEach(card => {
card.style.opacity = '0';
card.style.transform = 'translateY(24px)';
card.style.transition = 'opacity 0.4s ease, transform 0.4s ease';
});
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}, index * 100); // staggered effect
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.15 }
);
cards.forEach(card => observer.observe(card));
})();
Проверка prefers-reduced-motion:
if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
initAnimations();
}
Типичные кастомные блоки
Таблица тарифов — одна из самых частых задач. Нестандартная визуализация сравнения планов недостижима стандартными блоками Tilda.
Интерактивная карта — Leaflet.js или Google Maps Embed API в Zero Block. Маркеры из массива данных, popup с адресом:
const map = L.map('zb-map').setView([53.9, 27.56], 12);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
const offices = [
{ lat: 53.9, lng: 27.56, name: 'Главный офис', address: 'ул. Примерная, 1' },
];
offices.forEach(office => {
L.marker([office.lat, office.lng])
.addTo(map)
.bindPopup(`<b>${office.name}</b><br>${office.address}`);
});
Счётчики с анимацией — анимированный числовой счётчик при попадании в viewport:
function animateCounter(el, target, duration = 1500) {
const start = performance.now();
const update = (time) => {
const progress = Math.min((time - start) / duration, 1);
const value = Math.round(progress * target);
el.textContent = value.toLocaleString('ru-RU');
if (progress < 1) requestAnimationFrame(update);
};
requestAnimationFrame(update);
}
Кастомная форма — с мультишаговой логикой, условными полями, загрузкой файлов. Стандартная форма Tilda не поддерживает многошаговые сценарии.
Горизонтальный scroll-слайдер — для галерей кейсов, отзывов:
const track = document.querySelector('.zb-slider__track');
let isDown = false;
let startX, scrollLeft;
track.addEventListener('mousedown', e => {
isDown = true;
startX = e.pageX - track.offsetLeft;
scrollLeft = track.scrollLeft;
});
track.addEventListener('mouseleave', () => isDown = false);
track.addEventListener('mouseup', () => isDown = false);
track.addEventListener('mousemove', e => {
if (!isDown) return;
const x = e.pageX - track.offsetLeft;
track.scrollLeft = scrollLeft - (x - startX);
});
Переиспользование блоков
Zero Block нельзя сохранить как глобальный компонент внутри Tilda. Обходные варианты:
- дублирование блока между страницами (синхронизация вручную)
- хранение HTML/CSS/JS в репозитории, копирование при необходимости
- Tilda «Мастер-блок» — обновление на всех страницах одновременно (функция платформы, не кастомный код)
Типичные сроки
Простой Zero Block (таблица, счётчики, кастомные карточки без сложной логики) — 1–2 рабочих дня. Интерактивный блок (многошаговая форма, карта с данными, слайдер с API) — 3–5 дней. Набор из 5–7 кастомных блоков для полного сайта — 7–12 дней.







