Задать вопрос директору
Telegram
VK
Звонок

Карусель отзывов клиентов веб-студии

Пять отзывов заказчиков в карусели с точками и стрелками. Слева компания, сфера и цифра результата, справа текст и подпись, на телефоне карточка складывается в одну колонку и листается свайпом.

  • ТипОтзывы
  • НишаIT и digital
  • Вес кода12.4 КБ
  • Заголовок H1нет, только H2
  • Форма Tildaнет
  • Интерактив
Живое демо — блок работает прямо здесь

Код блока

<section class="vboag">
  <div class="vboag-wrap">
    <div class="vboag-head">
      <h2 class="vboag-h2">Итоги проектов словами заказчиков</h2>
      <p class="vboag-lead">Пять компаний, с которыми мы работали дольше трёх месяцев. Цифры взяты из их отчётов через полгода после запуска.</p>
    </div>

    <div class="vboag-view">
      <div class="vboag-track" id="vboag-track"></div>
    </div>

    <div class="vboag-nav">
      <div class="vboag-dots" id="vboag-dots" role="tablist" aria-label="Отзывы клиентов"></div>
      <div class="vboag-arrs">
        <button type="button" class="vboag-arr" id="vboag-prev" aria-label="Предыдущий отзыв">
          <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M14.5 5.5L8 12l6.5 6.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
        </button>
        <button type="button" class="vboag-arr" id="vboag-next" aria-label="Следующий отзыв">
          <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9.5 5.5L16 12l-6.5 6.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
        </button>
      </div>
    </div>
  </div>
</section>

<style>
.vboag, .vboag *, .vboag *::before, .vboag *::after { box-sizing: border-box; }
.vboag {
  --acc: #6ee787; --bg: #0f1116; --panel: #171a21; --ink: #e9edf2; --muted: #8b95a5; --line: #262b34;
  --f: var(--t-text-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif);
  --fh: var(--t-headline-font, var(--f));
  background: var(--bg); color: var(--ink); font-family: var(--f); padding: clamp(36px, 5vw, 84px) 20px;
}
.vboag-wrap { max-width: 1120px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 40px); }
.vboag-head { max-width: 42em; margin-bottom: clamp(22px, 3vw, 34px); }
.vboag-h2 { font-family: var(--fh); font-size: clamp(26px, 3.4vw, 40px); line-height: 1.12; font-weight: 700; letter-spacing: -.02em; margin: 0 0 12px; }
.vboag-lead { font-size: 16px; line-height: 1.65; color: var(--muted); margin: 0; }

.vboag-view { overflow: hidden; border-radius: 22px; }
.vboag-track { display: flex; will-change: transform; transition: transform .45s cubic-bezier(.22,1,.36,1); }
.vboag-slide { flex: 0 0 100%; min-width: 100%; background: var(--panel); border: 1px solid var(--line); border-radius: 22px;
  display: grid; grid-template-columns: minmax(0, .78fr) minmax(0, 1.22fr); gap: clamp(20px, 3vw, 44px);
  padding: clamp(22px, 3vw, 40px); }
.vboag-side { display: flex; flex-direction: column; }
.vboag-co { font-family: var(--fh); font-size: 19px; font-weight: 700; margin: 0 0 6px; }
.vboag-field { font-size: 13px; color: var(--muted); margin: 0 0 18px; }
.vboag-work { list-style: none; margin: 0 0 auto; padding: 0; display: flex; flex-wrap: wrap; gap: 7px; }
.vboag-work li { font-size: 12.5px; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; }
.vboag-num { margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--line); }
.vboag-num b { display: block; font-family: var(--fh); font-size: clamp(30px, 4vw, 44px); line-height: 1; font-weight: 700; color: var(--acc); letter-spacing: -.02em; }
.vboag-num span { display: block; font-size: 13px; line-height: 1.5; color: var(--muted); margin-top: 9px; }

.vboag-body { display: flex; flex-direction: column; }
.vboag-txt { margin: 0 0 22px; font-size: clamp(15.5px, 1.7vw, 17.5px); line-height: 1.68; }
.vboag-who { display: flex; align-items: center; gap: 12px; margin-top: auto; padding-top: 18px; border-top: 1px solid var(--line); }
.vboag-ini { flex: 0 0 42px; width: 42px; height: 42px; border-radius: 50%; background: rgba(110, 231, 135, .14); color: var(--acc);
  display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700; }
.vboag-who b { display: block; font-size: 15px; font-weight: 600; }
.vboag-who span { display: block; font-size: 12.5px; color: var(--muted); margin-top: 2px; }

.vboag-nav { display: flex; align-items: center; gap: 16px; margin-top: 20px; }
.vboag-dots { display: flex; flex-wrap: wrap; gap: 8px; }
.vboag-dot { width: 26px; height: 8px; border: 0; margin: 0; padding: 0; -webkit-appearance: none; appearance: none; cursor: pointer;
  border-radius: 999px; background: #2c323b !important; transition: background .25s ease, width .25s ease; }
.vboag-dot:hover { background: #3d4552 !important; }
.vboag-dot[aria-selected="true"] { width: 40px; background: var(--acc) !important; }
.vboag-arrs { display: flex; gap: 10px; margin-left: auto; }
.vboag-arr { width: 46px; height: 46px; border-radius: 50%; border: 1px solid var(--line); margin: 0; padding: 0;
  -webkit-appearance: none; appearance: none; cursor: pointer; background: none !important; color: var(--ink) !important;
  display: flex; align-items: center; justify-content: center; transition: .18s ease; }
.vboag-arr svg { width: 22px; height: 22px; }
.vboag-arr:hover { border-color: var(--acc); color: var(--acc) !important; }

@media (max-width: 820px) { .vboag-slide { grid-template-columns: minmax(0, 1fr); } .vboag-num { margin-top: 20px; } }
@media (prefers-reduced-motion: reduce) { .vboag-track, .vboag-dot, .vboag-arr { transition: none !important; } }
</style>

<script>
(function () {
  /* ── ОТЗЫВЫ КЛИЕНТОВ ── */
  var CASES = [
    { co: 'Фабрика света', field: 'Производство светильников, Киров',
      work: ['Каталог с фильтрами', 'Обмен с 1С', 'Личный кабинет дилера'],
      num: '+38%', numTxt: 'заявок с сайта за четыре месяца после запуска',
      text: 'Старый сайт держал 900 позиций, из которых половина была снята с производства. Ребята начали со склада: разобрали свойства, собрали фильтры и настроили обмен, теперь остатки подтягиваются каждую ночь. Менеджеры перестали отвечать на вопрос «есть ли в наличии», и это освободило им день в неделю.',
      who: 'Марина Гущина', role: 'Коммерческий директор' },
    { co: 'Клиника Ясная', field: 'Многопрофильная клиника, Тверь',
      work: ['Многостраничный сайт', 'Запись через виджет', 'Страницы врачей'],
      num: '+52%', numTxt: 'записей через сайт вместо звонков в регистратуру',
      text: 'Мы просили сделать «как у сетевых», но после разбора обращений остановились на другом: отдельная страница под каждого врача и понятная кнопка записи в шапке. За полгода нагрузка на регистратуру снизилась заметно, пациенты стали приходить подготовленными и с меньшим числом вопросов по цене.',
      who: 'Олег Бабенко', role: 'Управляющий' },
    { co: 'Северный лес', field: 'Строительство домов, Вологда',
      work: ['Одностраничный сайт', 'Квиз подбора проекта', 'Аналитика'],
      num: '34%', numTxt: 'на столько снизилась стоимость обращения',
      text: 'До этого мы вели рекламу на страницу с общими словами и получали заявки без бюджета и участка. Квиз отсекает тех, кто зашёл посмотреть картинки, и приводит человека с готовым набором ответов. Менеджер видит их до звонка, поэтому разговор начинается сразу с проекта.',
      who: 'Дмитрий Хвостов', role: 'Владелец' },
    { co: 'Точка сбора', field: 'Сеть кофеен, Казань',
      work: ['Сайт доставки', 'Карта точек', 'Программа гостя'],
      num: '+21%', numTxt: 'повторных заказов за три месяца',
      text: 'Проект вели по этапам, и это оказалось удобно: после сборки витрины мы запустились, а карту точек и накопительную программу добавили следующим месяцем. Правки принимали в общем чате, каждую пятницу приходил список сделанного. Ни одного срыва срока за весь проект.',
      who: 'Алина Тер-Григорян', role: 'Руководитель по маркетингу' },
    { co: 'Профит-Аудит', field: 'Бухгалтерские услуги, Самара',
      work: ['Сайт услуг', 'Калькулятор тарифа', 'База статей'],
      num: '+46%', numTxt: 'обращений после запуска калькулятора',
      text: 'Главным вопросом клиентов была цена, а прайс на сайте её только запутывал. Вместо таблицы поставили расчёт по числу сотрудников и системе налогов, с вилкой и списком того, что входит. Люди стали писать уже с суммой на руках, разговор идёт короче и предметнее.',
      who: 'Ирина Соболева', role: 'Партнёр' }
  ];

  var roots = document.querySelectorAll('.vboag');
  for (var i = 0; i < roots.length; i++) init(roots[i]);

  function init(root) {
    if (root.__vb) return; root.__vb = 1;
    var track = root.querySelector('#vboag-track'), dots = root.querySelector('#vboag-dots');
    var prev = root.querySelector('#vboag-prev'), next = root.querySelector('#vboag-next');
    var idx = 0;

    track.innerHTML = CASES.map(function (c, n) {
      var ini = c.who.split(' ').map(function (w) { return w.charAt(0); }).join('').slice(0, 2);
      return '<article class="vboag-slide" id="vboag-s' + n + '" role="tabpanel">' +
        '<div class="vboag-side"><h3 class="vboag-co">' + c.co + '<\/h3>' +
        '<p class="vboag-field">' + c.field + '<\/p>' +
        '<ul class="vboag-work">' + c.work.map(function (w) { return '<li>' + w + '<\/li>'; }).join('') + '<\/ul>' +
        '<div class="vboag-num"><b>' + c.num + '<\/b><span>' + c.numTxt + '<\/span><\/div><\/div>' +
        '<div class="vboag-body"><p class="vboag-txt">' + c.text + '<\/p>' +
        '<div class="vboag-who"><span class="vboag-ini">' + ini + '<\/span>' +
        '<span><b>' + c.who + '<\/b><span>' + c.role + ', ' + c.co + '<\/span><\/span><\/div><\/div><\/article>';
    }).join('');

    dots.innerHTML = CASES.map(function (c, n) {
      return '<button type="button" class="vboag-dot" role="tab" data-i="' + n + '" aria-controls="vboag-s' + n + '"' +
        ' aria-selected="' + (n === 0 ? 'true' : 'false') + '" aria-label="Отзыв ' + (n + 1) + ': ' + c.co + '"><\/button>';
    }).join('');

    var buttons = dots.querySelectorAll('.vboag-dot');

    function go(n) {
      idx = (n + CASES.length) % CASES.length;
      track.style.transform = 'translateX(' + (-idx * 100) + '%)';
      for (var i = 0; i < buttons.length; i++) {
        buttons[i].setAttribute('aria-selected', i === idx ? 'true' : 'false');
      }
    }

    for (var i = 0; i < buttons.length; i++) {
      buttons[i].addEventListener('click', function () { go(+this.getAttribute('data-i')); });
    }
    prev.addEventListener('click', function () { go(idx - 1); });
    next.addEventListener('click', function () { go(idx + 1); });

    var x0 = null;
    track.addEventListener('touchstart', function (e) { x0 = e.touches[0].clientX; }, { passive: true });
    track.addEventListener('touchend', function (e) {
      if (x0 === null) return;
      var d = e.changedTouches[0].clientX - x0;
      if (Math.abs(d) > 45) go(idx + (d < 0 ? 1 : -1));
      x0 = null;
    }, { passive: true });

    go(0);
  }
})();
</script>

Вставляется целиком в блок T123 «HTML-код». Внутри уже есть стили и скрипт, подключать ничего не нужно.

Как вставить блок в Tilda

  1. Скопируйте кодКнопка «Скопировать код» выше кладёт всё содержимое в буфер обмена.
  2. Добавьте блок T123В редакторе страницы: «Библиотека блоков» → «Другое» → T123 «HTML-код».
  3. Вставьте и сохранитеНажмите «Контент», вставьте код в поле, сохраните и обновите страницу.
  4. ОпубликуйтеВ превью скрипты Tilda работают не всегда — проверяйте на опубликованной странице.

Подробная инструкция с граблями — как вставить вайб-блок в Tilda.

Что менять под себя

Где в кодеЗа что отвечает
массив CASES в начале скриптакомпании, сферы, состав работ, цифры и тексты
поля num и numTxtкрупная цифра результата и подпись под ней
массив work у отзываметки работ, которые выполняли на проекте
поля who и roleимя и должность человека под текстом
--acc в стиляхцвет цифры, активной точки и наведения на стрелки

Отзывы клиентов агентства: зачем он нужен

Отзыв о работе агентства читают ради одного: получилось у соседа по рынку или нет. Поэтому в карточке рядом с текстом стоит проверяемая цифра: рост заявок, снижение стоимости обращения, доля повторных заказов. Метки над цифрой показывают, что именно делали на проекте, и связывают результат с работой. Подпись с должностью закрывает вопрос о том, кто эти слова сказал.

Карусель показывает по одному отзыву, поэтому длинный текст читается целиком без обрезки. Листается стрелками, точками и свайпом, точка активного отзыва вытягивается в полоску, так что позиция видна без счётчика. Все данные лежат в массиве CASES, точки рисуются по его длине. Плавный сдвиг отключается, когда посетитель включил режим уменьшенной анимации.

Вопросы по этому блоку

  • Допишите объект в массив CASES. Шестая точка появится сама, потому что индикаторы рисуются по длине массива, а ширина карточки задана в процентах.

  • Да, карусель ловит свайп по карточке: сдвиг больше 45 пикселей переключает отзыв. Стрелки и точки при этом продолжают работать, а с клавиатуры доступны обе кнопки.

  • Удалите блок с классом vboag-num из шаблона карточки в скрипте. Левая колонка останется с названием компании, сферой и метками работ, вёрстка не сломается.

  • Да. Код на этой странице копируется целиком, без регистрации и подписки. Указывать авторство не нужно, использовать можно в коммерческих проектах.

  • Нет. Все классы внутри имеют собственный префикс vboag, поэтому не пересекаются ни со стилями Tilda, ни с другими блоками. Скрипт привязан к своему элементу и запускается один раз, даже если блок вставлен дважды.

  • Раскладка перестраивается под узкие экраны, размеры заданы через clamp, поля ввода имеют шрифт 16 пикселей — iOS не будет зумить страницу при фокусе. Отдельной мобильной версии подключать не нужно.

Другие блоки отзывов

Ещё блоки для IT и digital-услуг

Собрать сайт целиком, а не по блокам

Дровосеки делают сайты на Tilda под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.