Квиз подбора товара для интернет-магазина
Четыре вопроса вместо длинного каталога: квиз спрашивает, кому и для чего нужен товар, и выдаёт одну позицию с ценой, тремя параметрами и обоснованием выбора.
<section class="vbkpt2">
<div class="vbkpt2-wrap">
<div class="vbkpt2-head">
<h2 class="vbkpt2-h2">Подберём позицию за четыре вопроса</h2>
<p class="vbkpt2-lead">Спросим, кому нужна посуда, для какой задачи и на какую сумму рассчитываете. В конце покажем позицию из каталога с ценой и обоснованием.</p>
</div>
<div class="vbkpt2-box">
<div class="vbkpt2-bar" aria-hidden="true"><i id="vbkpt2-fill"></i></div>
<div class="vbkpt2-dots" id="vbkpt2-dots"></div>
<div class="vbkpt2-stage" id="vbkpt2-stage" aria-live="polite"></div>
<div class="vbkpt2-foot">
<button type="button" class="vbkpt2-back" id="vbkpt2-back" hidden>Вернуться к прошлому вопросу</button>
<span class="vbkpt2-step" id="vbkpt2-step"></span>
</div>
</div>
</div>
</section>
<style>
.vbkpt2, .vbkpt2 *, .vbkpt2 *::before, .vbkpt2 *::after { box-sizing: border-box; }
.vbkpt2 {
--acc: #9c2b45; --acc-dark: #7d2036; --ink: #1e1c1b; --muted: #6b6561; --line: #e4e0dc; --soft: #f7f5f2;
--f: var(--t-text-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif);
--fh: var(--t-headline-font, var(--f));
background: var(--soft); color: var(--ink); font-family: var(--f); padding: clamp(36px, 5vw, 84px) 20px;
}
.vbkpt2-wrap { max-width: 900px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 38px); }
.vbkpt2-head { margin-bottom: clamp(20px, 2.6vw, 30px); }
.vbkpt2-h2 { font-family: var(--fh); font-size: clamp(25px, 3.2vw, 38px); line-height: 1.12; font-weight: 700;
letter-spacing: -.02em; margin: 0 0 12px; }
.vbkpt2-lead { font-size: 16px; line-height: 1.62; color: var(--muted); margin: 0; max-width: 44em; }
.vbkpt2-box { background: #fff; border: 1px solid var(--line); border-radius: 24px; padding: clamp(22px, 3vw, 40px); }
.vbkpt2-bar { height: 3px; border-radius: 3px; background: var(--line); overflow: hidden; }
.vbkpt2-bar i { display: block; height: 100%; width: 0; border-radius: 3px; background: var(--acc);
transition: width .4s cubic-bezier(.22,1,.36,1); }
.vbkpt2-dots { display: flex; gap: 7px; margin: 14px 0 24px; }
.vbkpt2-dot { font-size: 11.5px; letter-spacing: .04em; color: #a8a29c; }
.vbkpt2-dot--on { color: var(--acc); font-weight: 600; }
.vbkpt2-q { font-family: var(--fh); font-size: clamp(19px, 2.1vw, 25px); line-height: 1.28; font-weight: 600; margin: 0 0 20px; }
.vbkpt2-opts { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; }
.vbkpt2-opt { display: block; width: 100%; border: 1.5px solid var(--line); margin: 0; padding: 18px 20px; appearance: none;
font: inherit; cursor: pointer; text-align: left; border-radius: 15px; background: #fff !important; color: var(--ink) !important;
transition: border-color .18s ease; }
.vbkpt2-opt:hover { border-color: var(--acc); }
.vbkpt2-opt b { display: block; font-size: 15.5px; font-weight: 600; margin-bottom: 5px; }
.vbkpt2-opt i { display: block; font-style: normal; font-size: 13px; line-height: 1.5; color: var(--muted); }
.vbkpt2-foot { display: flex; align-items: center; gap: 14px; margin-top: 22px; }
.vbkpt2-back { border: 0; margin: 0; padding: 0; appearance: none; background: none !important; cursor: pointer;
font: inherit; font-size: 14px; color: var(--muted) !important; text-decoration: underline; }
.vbkpt2-back:hover { color: var(--acc) !important; }
.vbkpt2-step { margin-left: auto; font-size: 13px; color: var(--muted); }
.vbkpt2-res__tag { display: inline-block; font-size: 12px; font-weight: 600; color: var(--acc); background: var(--soft);
border-radius: 999px; padding: 7px 14px; margin-bottom: 14px; }
.vbkpt2-res__ttl { font-family: var(--fh); font-size: clamp(22px, 2.7vw, 30px); line-height: 1.18; font-weight: 700; margin: 0 0 10px; }
.vbkpt2-res__price { font-family: var(--fh); font-size: 26px; font-weight: 700; color: var(--acc); margin: 0 0 14px; }
.vbkpt2-res__price em { font-style: normal; font-size: 14px; font-weight: 500; color: var(--muted); margin-left: 8px; }.vbkpt2-res__txt { font-size: 15.5px; line-height: 1.65; color: var(--muted); margin: 0 0 20px; max-width: 42em; }
.vbkpt2-res__facts { list-style: none; margin: 0 0 24px; padding: 0; display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.vbkpt2-res__facts li { background: var(--soft); border-radius: 13px; padding: 14px 16px; }
.vbkpt2-res__facts b { display: block; font-family: var(--fh); font-size: 17px; font-weight: 700; margin-bottom: 3px; }
.vbkpt2-res__facts span { display: block; font-size: 12.5px; color: var(--muted); }
.vbkpt2-acts { display: flex; flex-wrap: wrap; gap: 10px; }
.vbkpt2-cta, .vbkpt2-cta:link, .vbkpt2-cta:visited, .vbkpt2-cta:focus { display: inline-flex; align-items: center;
justify-content: center; min-height: 54px; padding: 0 28px; border-radius: 12px; font-size: 16px; font-weight: 600;
background: var(--acc); color: #fff !important; text-decoration: none !important; }
.vbkpt2-cta:hover { background: var(--acc-dark); color: #fff !important; }
.vbkpt2-again { min-height: 54px; padding: 0 24px; border: 1.5px solid var(--line); margin: 0; appearance: none;
font: inherit; font-size: 16px; cursor: pointer; border-radius: 12px; background: #fff !important; color: var(--ink) !important; }
@media (max-width: 560px) { .vbkpt2-opts { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) { .vbkpt2 * { transition: none !important; } }
</style>
<script>
(function () {
/* ── ВОПРОСЫ: p — очки позициям каталога ── */
var STEPS = [
{ q: 'Кому берёте посуду?', short: 'Для кого', opts: [
{ t: 'Себе, живу один или вдвоём', d: 'Пара кружек и тарелок', p: { zavtrak: 2, stol: 0, kastrulya: 1, banki: 1 } },
{ t: 'Семье из трёх человек и больше', d: 'Нужен запас предметов', p: { zavtrak: 0, stol: 3, kastrulya: 2, banki: 1 } },
{ t: 'В подарок', d: 'Важен вид набора', p: { zavtrak: 3, stol: 1, kastrulya: 0, banki: 1 } }
]},
{ q: 'Какую задачу закрываете?', short: 'Задача', opts: [
{ t: 'Завтраки и чай', d: 'Кружки и малые тарелки', p: { zavtrak: 3, stol: 1, kastrulya: 0, banki: 0 } },
{ t: 'Готовка каждый день', d: 'Кастрюли всё время в работе', p: { zavtrak: 0, stol: 0, kastrulya: 3, banki: 1 } },
{ t: 'Сервировка стола', d: 'Гости и ровный комплект', p: { zavtrak: 1, stol: 3, kastrulya: 0, banki: 0 } },
{ t: 'Порядок на полках', d: 'Крупы лежат в пакетах', p: { zavtrak: 0, stol: 0, kastrulya: 0, banki: 3 } }
]},
{ q: 'На какую сумму рассчитываете?', short: 'Бюджет', opts: [
{ t: 'До 3 000 ₽', d: 'Одна вещь или малый набор', p: { zavtrak: 2, stol: 0, kastrulya: 0, banki: 3 } },
{ t: 'От 3 000 до 6 000 ₽', d: 'Набор на двоих', p: { zavtrak: 3, stol: 1, kastrulya: 3, banki: 1 } },
{ t: 'Больше 6 000 ₽', d: 'Комплект на семью', p: { zavtrak: 0, stol: 3, kastrulya: 2, banki: 0 } }
]},
{ q: 'Что для вас важнее в посуде?', short: 'Свойство', opts: [
{ t: 'Переносит духовку и посудомойку', d: 'Машина и духовка', p: { zavtrak: 1, stol: 2, kastrulya: 3, banki: 0 } },
{ t: 'Спокойный вид и одинаковый оттенок', d: 'Всё смотрится комплектом', p: { zavtrak: 2, stol: 3, kastrulya: 0, banki: 1 } },
{ t: 'Плотная крышка и герметичность', d: 'Продукты держат аромат', p: { zavtrak: 0, stol: 0, kastrulya: 1, banki: 3 } }
]}
];
/* ── ПОЗИЦИИ КАТАЛОГА ── */
var GOODS = {
zavtrak: { ttl: 'Набор для завтрака: 2 кружки и 2 тарелки', price: '3 240 ₽', old: 'вместо 3 860 ₽ поштучно', href: '#katalog-zavtrak',
txt: 'Посуда на одного или двоих при умеренной сумме. Все четыре предмета из одной партии обжига, оттенок совпадает, коробка годится для подарка.',
facts: [['350 мл', 'объём кружки'], ['21 см', 'диаметр тарелки'], ['1 день', 'срок сборки заказа']] },
stol: { ttl: 'Столовый комплект «Гладь» на четыре персоны', price: '8 900 ₽', old: '16 предметов в комплекте', href: '#katalog-stol',
txt: 'Ровный комплект на семью и гостей: тарелки трёх диаметров и салатники из одной поставки глазури. Машина и духовка ему не вредят.',
facts: [['16 предметов', 'в одной коробке'], ['4 персоны', 'рассчитан на'], ['до 220 градусов', 'выдерживает в духовке']] },
kastrulya: { ttl: 'Кастрюля с крышкой, сталь, 3 литра', price: '5 400 ₽', old: 'дно с тройным слоем', href: '#katalog-kastrulya',
txt: 'Когда готовят каждый день, важнее выносливость. Дно с тройным слоем держит тепло, крышка ложится плотно, плита подойдёт любая.',
facts: [['3 литра', 'полезный объём'], ['5 мм', 'толщина дна'], ['10 лет', 'гарантия на корпус']] },
banki: { ttl: 'Три банки для хранения, крышки из бука', price: '2 460 ₽', old: '0,7 литра каждая', href: '#katalog-hranenie',
txt: 'Порядок на полках держится на герметичности. Кольцо в крышке запирает запах, кофе и специи стоят рядом, а через стенку виден остаток крупы.',
facts: [['0,7 литра', 'объём одной банки'], ['3 штуки', 'в комплекте'], ['бук', 'материал крышки']] }
};
var roots = document.querySelectorAll('.vbkpt2');
for (var i = 0; i < roots.length; i++) init(roots[i]);
function init(root) {
if (root.__vb) return; root.__vb = 1;
var idx = 0, score, trail;
var stage = root.querySelector('#vbkpt2-stage'), fill = root.querySelector('#vbkpt2-fill');
var back = root.querySelector('#vbkpt2-back'), step = root.querySelector('#vbkpt2-step');
var dots = root.querySelector('#vbkpt2-dots');
function reset() { idx = 0; score = { zavtrak: 0, stol: 0, kastrulya: 0, banki: 0 }; trail = []; }
function drawDots(done) {
var out = '';
for (var d = 0; d < STEPS.length; d++) {
out += '<span class="vbkpt2-dot' + (done || d <= idx ? ' vbkpt2-dot--on' : '') + '">' + STEPS[d].short + '<\/span>';
}
dots.innerHTML = out;
}
function drawStep() {
var s = STEPS[idx];
fill.style.width = (idx / STEPS.length * 100) + '%';
step.textContent = 'Вопрос ' + (idx + 1) + ' из ' + STEPS.length;
back.hidden = idx === 0;
drawDots(false);
var html = '<h3 class="vbkpt2-q">' + s.q + '<\/h3><div class="vbkpt2-opts">';
for (var o = 0; o < s.opts.length; o++) {
html += '<button type="button" class="vbkpt2-opt" data-i="' + o + '"><b>' + s.opts[o].t + '<\/b><i>' + s.opts[o].d + '<\/i><\/button>';
}
stage.innerHTML = html + '<\/div>';
var btns = stage.querySelectorAll('.vbkpt2-opt');
for (var b = 0; b < btns.length; b++) {
btns[b].addEventListener('click', function () { choose(s.opts[parseInt(this.getAttribute('data-i'), 10)]); });
}
}
function choose(opt) {
trail.push(opt.p);
for (var k in opt.p) { if (opt.p.hasOwnProperty(k)) score[k] += opt.p[k]; }
idx++;
if (idx < STEPS.length) drawStep(); else drawResult();
}
function drawResult() {
fill.style.width = '100%';
step.textContent = 'Готово';
back.hidden = false;
drawDots(true);
var win = 'zavtrak', keys = ['zavtrak', 'stol', 'kastrulya', 'banki'];
for (var k = 1; k < keys.length; k++) { if (score[keys[k]] > score[win]) win = keys[k]; }
var g = GOODS[win], facts = '';
for (var f = 0; f < g.facts.length; f++) {
facts += '<li><b>' + g.facts[f][0] + '<\/b><span>' + g.facts[f][1] + '<\/span><\/li>';
}
stage.innerHTML = '<div class="vbkpt2-res"><span class="vbkpt2-res__tag">Подходит вам<\/span>' +
'<h3 class="vbkpt2-res__ttl">' + g.ttl + '<\/h3>' +
'<p class="vbkpt2-res__price">' + g.price + '<em>' + g.old + '<\/em><\/p>' +
'<p class="vbkpt2-res__txt">' + g.txt + '<\/p>' +
'<ul class="vbkpt2-res__facts">' + facts + '<\/ul>' +
'<div class="vbkpt2-acts"><a class="vbkpt2-cta" href="' + g.href + '">Открыть в каталоге<\/a>' +
'<button type="button" class="vbkpt2-again">Пройти заново<\/button><\/div><\/div>';
var again = stage.querySelector('.vbkpt2-again');
if (again) again.addEventListener('click', function () { reset(); drawStep(); });
}
back.addEventListener('click', function () {
if (idx === 0) return;
idx--;
var p = trail.pop();
if (p) { for (var k in p) { if (p.hasOwnProperty(k)) score[k] -= p[k]; } }
drawStep();
});
reset();
drawStep();
}
})();
</script> Вставляется целиком в блок T123 «HTML-код». Внутри уже есть стили и скрипт, подключать ничего не нужно.
Как вставить блок в Tilda
- Скопируйте кодКнопка «Скопировать код» выше кладёт всё содержимое в буфер обмена.
- Добавьте блок T123В редакторе страницы: «Библиотека блоков» → «Другое» → T123 «HTML-код».
- Вставьте и сохранитеНажмите «Контент», вставьте код в поле, сохраните и обновите страницу.
- ОпубликуйтеВ превью скрипты Tilda работают не всегда — проверяйте на опубликованной странице.
Подробная инструкция с граблями — как вставить вайб-блок в Tilda.
Что менять под себя
| Где в коде | За что отвечает |
|---|---|
STEPS в начале скрипта | вопросы, варианты ответов и очки каждому товару |
GOODS в начале скрипта | позиции каталога: название, цена, обоснование, три параметра |
href внутри GOODS | адреса карточек товара, куда ведёт кнопка результата |
--acc в начале стилей | цвет полосы прогресса, рамок и кнопки в результате |
Квиз подбора товара: зачем он нужен
Каталог из двухсот позиций пугает человека, который зашёл выбрать подарок. Квиз сужает выбор до одной вещи за четыре шага: для кого, какая задача, какая сумма и что важнее в изделии. Ответы складываются в очки по четырём товарам, побеждает набравший больше, поэтому результат меняется даже при похожих сценариях.
Наверху идёт полоса прогресса и названия шагов, внизу ссылка на предыдущий вопрос: очки за отменённый ответ вычитаются обратно, и повтор шага не портит подсчёт. Результат показывает название позиции, цену, короткое объяснение и три параметра вроде объёма и срока сборки. Оттуда ведёт кнопка в каталог и кнопка пройти заново.
Вопросы по этому блоку
-
Допишите объект в массив STEPS: поле q для вопроса, short для подписи в полосе шагов и opts с вариантами. Полоса прогресса и счётчик считают шаги сами, править разметку не нужно.
-
Да. Добавьте ключ в GOODS и такой же ключ в очки каждого варианта ответа, а также в массив keys внутри функции подсчёта. Остальная логика работает с любым числом позиций.
-
Никуда: расчёт живёт в браузере, форм в блоке нет. Цель квиза перевести человека в каталог по ссылке из результата, поэтому подставьте туда рабочие адреса карточек.
-
Да. Код на этой странице копируется целиком, без регистрации и подписки. Указывать авторство не нужно, использовать можно в коммерческих проектах.
-
Нет. Все классы внутри имеют собственный префикс vbkpt2, поэтому не пересекаются ни со стилями Tilda, ни с другими блоками. Скрипт привязан к своему элементу и запускается один раз, даже если блок вставлен дважды.
-
Раскладка перестраивается под узкие экраны, размеры заданы через clamp, поля ввода имеют шрифт 16 пикселей — iOS не будет зумить страницу при фокусе. Отдельной мобильной версии подключать не нужно.
Другие квизы
Ещё блоки для товарных брендов
Собрать сайт целиком, а не по блокам
Дровосеки делают сайты на Tilda под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.