Содержание
  1. Содержание
  2. Зачем нужна многошаговая форма
  3. Когда использовать
  4. Как разбить на шаги
  5. HTML-структура
  6. CSS-стили
  7. JS-логика переходов
  8. Валидация по шагам
  9. Сохранение прогресса при выходе
  10. Отправка формы
  11. Приёмы повышения конверсии
  12. Частые ошибки
  13. FAQ
  14. Чек-лист многошаговой формы
  15. Заключение

Длинная форма с 10 полями на одном экране пугает посетителей — конверсия падает. Та же форма, разбитая на 3-4 коротких шага, даёт в 1.5-2 раза больше заявок. Почему так работает: каждый шаг — небольшое психологическое обязательство, отвечать на короткие вопросы проще, прогресс-бар стимулирует дойти до конца. В статье — готовый код многошаговой формы на чистом HTML+JS, без библиотек, с валидацией, сохранением прогресса и отправкой данных.

Содержание

  1. Зачем нужна многошаговая форма
  2. Когда использовать
  3. Как разбить на шаги
  4. HTML-структура
  5. CSS-стили
  6. JS-логика переходов
  7. Валидация по шагам
  8. Сохранение прогресса при выходе
  9. Отправка формы
  10. Приёмы повышения конверсии
  11. Частые ошибки
  12. FAQ
  13. Чек-лист

Зачем нужна многошаговая форма

  • Снижает страх формы. 3 поля на экране не пугают, как 10.
  • Эффект вовлечения. Заполнил один шаг — психологически обязан продолжить.
  • Прогресс мотивирует. «Осталось 1 из 3» — стимул дойти до конца.
  • Можно собрать больше данных. Тот, кто прошёл шаг 1, спокойно заполнит и шаг 3.
  • Аналитика воронки. Видно, на каком шаге отваливаются — можно оптимизировать.

Когда использовать

Многошаговая форма выгодна, когда:

  • Нужно собрать 5+ полей данных;
  • Аудитория «холодная» — нужно их «прогреть» в процессе;
  • Продукт сложный — много параметров;
  • Высокая стоимость лида — оправдывает усложнение.

НЕ нужна, когда:

  • Только 2-3 поля (имя + телефон);
  • Аудитория готовая и нетерпеливая;
  • Простой массовый продукт.

Как разбить на шаги

Правильное разбиение — это половина успеха.

  1. Сначала простые вопросы. Тип услуги, выбор из вариантов — не требует усилий.
  2. Потом более сложные. Параметры, объём, требования.
  3. Контакты в конце. Когда пользователь уже инвестирован.

Пример для лендинга ремонта:

  • Шаг 1: Тип помещения (квартира / дом / офис).
  • Шаг 2: Площадь.
  • Шаг 3: Тип ремонта (косметический, евро, дизайнерский).
  • Шаг 4: Контакты (имя, телефон).

HTML-структура

<form id="multistep-form">
  <!-- Прогресс -->
  <div class="progress-bar">
    <div class="progress-fill" id="progress-fill"></div>
  </div>
  <p class="step-counter">Шаг <span id="current">1</span> из 4</p>

  <!-- Шаг 1 -->
  <div class="form-step active" data-step="1">
    <h2>Тип помещения?</h2>
    <label><input type="radio" name="type" value="квартира" required> Квартира</label>
    <label><input type="radio" name="type" value="дом" required> Дом</label>
    <label><input type="radio" name="type" value="офис" required> Офис</label>
    <button type="button" class="next-btn">Далее</button>
  </div>

  <!-- Шаг 2 -->
  <div class="form-step" data-step="2">
    <h2>Площадь, м²?</h2>
    <input type="number" name="area" min="1" required>
    <button type="button" class="prev-btn">Назад</button>
    <button type="button" class="next-btn">Далее</button>
  </div>

  <!-- Шаг 3 -->
  <div class="form-step" data-step="3">
    <h2>Тип ремонта?</h2>
    <label><input type="radio" name="kind" value="косметический" required> Косметический</label>
    <label><input type="radio" name="kind" value="евро" required> Евро</label>
    <label><input type="radio" name="kind" value="дизайнерский" required> Дизайнерский</label>
    <button type="button" class="prev-btn">Назад</button>
    <button type="button" class="next-btn">Далее</button>
  </div>

  <!-- Шаг 4 (финальный) -->
  <div class="form-step" data-step="4">
    <h2>Куда отправить расчёт?</h2>
    <input type="text" name="name" placeholder="Имя" required>
    <input type="tel" name="phone" placeholder="Телефон" required>
    <button type="button" class="prev-btn">Назад</button>
    <button type="submit">Получить расчёт</button>
  </div>
</form>

CSS-стили

.form-step { display: none; }
.form-step.active { display: block; }

.progress-bar {
  width: 100%;
  height: 6px;
  background: #eee;
  border-radius: 3px;
  margin-bottom: 1rem;
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  background: #4a5cf5;
  width: 25%;
  transition: width 0.3s;
}

.step-counter {
  text-align: center;
  color: #666;
  margin-bottom: 2rem;
}

.form-step label {
  display: block;
  padding: 1rem;
  margin: 0.5rem 0;
  border: 1px solid #ddd;
  border-radius: 6px;
  cursor: pointer;
}
.form-step label:hover { background: #f5f6ff; }

.form-step input[type="text"],
.form-step input[type="tel"],
.form-step input[type="number"] {
  width: 100%;
  padding: 1rem;
  margin: 0.5rem 0;
  border: 1px solid #ddd;
  border-radius: 6px;
  font-size: 1rem;
}

.next-btn, button[type="submit"] {
  width: 100%;
  padding: 1rem;
  background: #4a5cf5;
  color: white;
  border: none;
  border-radius: 6px;
  font-weight: 600;
  margin-top: 1rem;
  cursor: pointer;
}

.prev-btn {
  background: #eee;
  color: #333;
  border: none;
  padding: 0.75rem 1.5rem;
  border-radius: 6px;
  margin-right: 0.5rem;
  cursor: pointer;
}

JS-логика переходов

const form = document.getElementById('multistep-form');
const steps = form.querySelectorAll('.form-step');
const totalSteps = steps.length;
let currentStep = 1;

function showStep(step) {
  steps.forEach(s => s.classList.remove('active'));
  form.querySelector(`[data-step="${step}"]`).classList.add('active');
  document.getElementById('current').textContent = step;
  document.getElementById('progress-fill').style.width = (step / totalSteps * 100) + '%';
}

form.querySelectorAll('.next-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    const stepEl = btn.closest('.form-step');
    if (!validateStep(stepEl)) return;
    currentStep++;
    showStep(currentStep);
    ym(СЧЁТЧИК, 'reachGoal', `form_step_${currentStep}`);
  });
});

form.querySelectorAll('.prev-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    currentStep--;
    showStep(currentStep);
  });
});

Валидация по шагам

function validateStep(stepEl) {
  const inputs = stepEl.querySelectorAll('input[required]');
  for (const input of inputs) {
    if (input.type === 'radio') {
      const name = input.name;
      const checked = stepEl.querySelector(`input[name="${name}"]:checked`);
      if (!checked) {
        alert('Выберите вариант');
        return false;
      }
    } else if (!input.value.trim()) {
      input.focus();
      input.style.borderColor = 'red';
      return false;
    }
  }
  return true;
}

Сохранение прогресса при выходе

Если пользователь закрыл вкладку и вернулся — пусть продолжит с того места. Через localStorage:

// Сохраняем при изменении любого поля
form.addEventListener('input', () => {
  const data = {};
  new FormData(form).forEach((value, key) => { data[key] = value; });
  data._step = currentStep;
  localStorage.setItem('form_progress', JSON.stringify(data));
});

// Восстанавливаем при загрузке
window.addEventListener('load', () => {
  const saved = localStorage.getItem('form_progress');
  if (!saved) return;
  const data = JSON.parse(saved);
  for (const [key, value] of Object.entries(data)) {
    if (key === '_step') continue;
    const input = form.querySelector(`[name="${key}"]`);
    if (!input) continue;
    if (input.type === 'radio') {
      const radio = form.querySelector(`[name="${key}"][value="${value}"]`);
      if (radio) radio.checked = true;
    } else {
      input.value = value;
    }
  }
  if (data._step) {
    currentStep = data._step;
    showStep(currentStep);
  }
});

Отправка формы

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  const data = {};
  new FormData(form).forEach((value, key) => { data[key] = value; });

  const text = `🔔 Заявка
Тип: ${data.type}
Площадь: ${data.area} м²
Ремонт: ${data.kind}
Имя: ${data.name}
Телефон: ${data.phone}`;

  await fetch(`https://api.telegram.org/bot${TOKEN}/sendMessage`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ chat_id: CHAT_ID, text })
  });

  localStorage.removeItem('form_progress');
  ym(СЧЁТЧИК, 'reachGoal', 'form_complete');
  window.location.href = '/thank-you.html';
});

Приёмы повышения конверсии

  • Понятный CTA на каждом шаге. «Далее» лучше, чем «Submit». «Получить расчёт» лучше «Отправить».
  • Картинки в вариантах. Дизайн квартиры, типа ремонта — увеличивает вовлечение.
  • Прогресс-бар крупно. Чтобы пользователь видел путь.
  • Сначала легкие вопросы. Сначала кликнуть на вариант → потом печатать.
  • Социальное доказательство между шагами. «Уже подобрали ремонт для 1287 клиентов».
  • Подарок на финале. «Получите бесплатный 3D-эскиз планировки».
  • Адаптивность. На мобильном — отдельная вёрстка с большими кнопками.

Частые ошибки

  1. Слишком много шагов. Больше 5-6 — устают, бросают. Оптимум 3-4.
  2. Контакты в начале. Снижает конверсию в начале формы. Только в конце.
  3. Нет валидации по шагам. Пропускают пустые поля — данные неполные.
  4. Невозможно вернуться. Кнопка «Назад» обязательна.
  5. Нет прогресса. Пользователь не понимает, сколько осталось.
  6. Сложные вопросы. «Какой тип утеплителя?» — посетитель не знает.
  7. Не сохраняется прогресс. Случайно закрыл — начинай заново. Используйте localStorage.

FAQ

Сколько шагов оптимально?

3-5 шагов. До 3 — может не оправдать сложности. Больше 5 — устают. Главное — каждый шаг должен давать ценность.

Контакты в первом или последнем шаге?

В последнем. Психология: ответил на 3 вопроса → вложился → даст контакт. В начале — пугает, бросает.

Как замерить конверсию по шагам?

На каждом шаге отправляйте цель в Метрику: form_step_1, form_step_2, form_complete. В отчёте увидите воронку — где отваливаются.

Что лучше: одна длинная форма или многошаговая?

Если полей < 5 — одна форма. Если 5+ полей — многошаговая. Если форма требует выбора из вариантов (квиз-стиль) — многошаговая в любом случае.

Можно ли пропускать шаги?

Только если шаг необязательный — например, «Дополнительные пожелания». Обязательные данные пропускать нельзя.

Стоит ли сохранять прогресс?

Стоит. До 15% пользователей возвращаются. Если форма с нуля — большая часть бросает повторно. Если с сохранённым прогрессом — заканчивают.

Нужна ли валидация на JS, если HTML5 уже валидирует?

Да, для радио-кнопок (HTML5 required не всегда работает корректно в многошаговой) и для перехода между шагами. Иначе кликнул «Далее» с пустым полем — перешёл.

Чек-лист многошаговой формы

  • ☐ Форма разбита на 3-5 шагов
  • ☐ Шаги от простого к сложному
  • ☐ Контакты на последнем шаге
  • ☐ Прогресс-бар отображает текущий шаг
  • ☐ Кнопки «Далее» и «Назад» на каждом шаге
  • ☐ Валидация полей на каждом шаге
  • ☐ Прогресс сохраняется в localStorage
  • ☐ Отправка данных через Telegram/Email/CRM
  • ☐ Цели в Метрике на каждый шаг
  • ☐ Адаптивность на мобильных
  • ☐ Понятный CTA на финальной кнопке
  • ☐ Страница «Спасибо» после отправки

Заключение

Многошаговая форма — мощный инструмент роста конверсии в нишах со сложным продуктом и длинными формами. 3-4 коротких шага вместо одной длинной формы дают в полтора-два раза больше заявок. Реализуется на чистом HTML+JS за несколько часов, не требует библиотек и сервисов.

Готовые HTML-шаблоны Zettabyte часто содержат заготовки многошаговых форм — остаётся подключить обработчик и адаптировать вопросы. А для размещения лендинга подойдёт самый недорогой тариф из подборщика хостингов.