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

Блок отзывов клининговой компании для Tilda

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

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

Код блока

<section class="vbopu">
  <div class="vbopu-wrap">
    <div class="vbopu-top">
      <div class="vbopu-head">
        <h2 class="vbopu-h2">Что пишут после выезда бригады</h2>
        <p class="vbopu-lead">Анкету присылаем на следующий день, когда видно результат при дневном свете. Указываем объект, время работы и оценку без правок с нашей стороны.</p>
      </div>
      <div class="vbopu-score">
        <b id="vbopu-avg">4,8</b>
        <div class="vbopu-score__b">
          <span class="vbopu-stars" id="vbopu-stars" role="img" aria-label="Средняя оценка 4,8 из 5"></span>
          <span class="vbopu-score__t">348 анкет за последние полгода</span>
        </div>
      </div>
    </div>

    <div class="vbopu-grid" id="vbopu-grid"></div>

    <div class="vbopu-more">
      <button type="button" class="vbopu-btn" id="vbopu-more">Показать ещё отзывы</button>
    </div>
  </div>
</section>

<style>
.vbopu, .vbopu *, .vbopu *::before, .vbopu *::after { box-sizing: border-box; }
.vbopu {
  --acc: #0f8f7b; --star: #f2a93b; --ink: #16211f; --muted: #5b6f6b; --line: #dde9e6; --soft: #f1f7f5;
  --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, 80px) 20px;
}
.vbopu-wrap { max-width: 1180px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 40px); }
.vbopu-top { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, .6fr); gap: clamp(20px, 3vw, 48px);
  align-items: end; margin-bottom: clamp(22px, 3vw, 36px); }
.vbopu-head { max-width: 40em; }
.vbopu-h2 { font-family: var(--fh); font-size: clamp(26px, 3.4vw, 40px); line-height: 1.1; font-weight: 700; letter-spacing: -.02em; margin: 0 0 12px; }
.vbopu-lead { font-size: 16px; line-height: 1.6; color: var(--muted); margin: 0; }
.vbopu-score { display: flex; align-items: center; gap: 16px; background: #fff; border-radius: 18px; padding: 18px 22px; }
.vbopu-score b { font-family: var(--fh); font-size: 44px; line-height: 1; font-weight: 700; letter-spacing: -.03em; color: var(--acc); }
.vbopu-score__t { display: block; font-size: 12.5px; line-height: 1.45; color: var(--muted); margin-top: 7px; }

.vbopu-stars { display: inline-flex; gap: 3px; }
.vbopu-stars svg { width: 15px; height: 15px; fill: #d9e4e1; }
.vbopu-stars svg.vbopu-on { fill: var(--star); }

.vbopu-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; }
.vbopu-card { background: #fff; border-radius: 20px; padding: clamp(20px, 2.2vw, 26px); }
.vbopu-card--hid { display: none; }
.vbopu-card__top { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.vbopu-ava { flex: 0 0 44px; height: 44px; border-radius: 14px; background: var(--soft); display: flex; align-items: center;
  justify-content: center; font-family: var(--fh); font-size: 16px; font-weight: 700; color: var(--acc); }
.vbopu-card__n { display: block; font-size: 15.5px; font-weight: 600; }
.vbopu-card__d { display: block; font-size: 12.5px; color: var(--muted); margin-top: 3px; }
.vbopu-card__top .vbopu-stars { margin-left: auto; }
.vbopu-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 13px; }
.vbopu-tags span { font-size: 12.5px; line-height: 1.3; color: var(--muted); background: var(--soft); border-radius: 999px; padding: 7px 12px; }
.vbopu-card p { margin: 0; font-size: 14.5px; line-height: 1.65; color: var(--muted); }

.vbopu-more { display: flex; justify-content: center; margin-top: 18px; }
.vbopu-btn { min-height: 54px; padding: 0 30px; margin: 0; border: 1.5px solid var(--line); -webkit-appearance: none; appearance: none;
  font: inherit; font-size: 16px; font-weight: 600; cursor: pointer; border-radius: 13px; background: #fff !important; color: var(--ink) !important; transition: .18s ease; }
.vbopu-btn:hover { border-color: var(--acc); color: var(--acc) !important; }

@media (max-width: 860px) { .vbopu-top { grid-template-columns: minmax(0, 1fr); align-items: start; } }
@media (prefers-reduced-motion: reduce) { .vbopu * { transition: none !important; } }
</style>

<script>
(function () {
  var REVIEWS = [
    { n: 'Марина К.', o: 'Двушка после ремонта, 58 м²', h: 'работали 7 часов', d: 'март', r: 5,
      t: 'Строители ушли, а пыль осталась даже на верхних полках шкафа. Приехали втроём, прошли квартиру трижды, сняли плёнку с окон и следы клея с ламината. Вечером я въехала и ничего не переделывала.' },
    { n: 'Дмитрий С.', o: 'Офис 200 м², 12 рабочих мест', h: 'выезд по графику, 3 часа', d: 'февраль', r: 5,
      t: 'Убирают после закрытия, ключи и сигнализация на них. За четыре месяца ни одного пропуска и ни одной жалобы от сотрудников. Расходники в санузлах пополняют сами, счета приходят одним документом.' },
    { n: 'Ольга В.', o: 'Генеральная уборка, трёшка 82 м²', h: 'работали 6 часов', d: 'январь', r: 5,
      t: 'Просила уделить внимание кухне: вытяжка не мылась года два. Отмыли до металла, заодно сняли налёт в душевой, о котором я даже не говорила. Приняла работу по списку в приложении, всё сошлось.' },
    { n: 'Артём П.', o: 'Мытьё окон, 9 створок', h: 'работали 2 часа', d: 'апрель', r: 4,
      t: 'Окна вымыли хорошо, разводов нет даже на солнце. Снял одну звезду за опоздание на сорок минут: попали в пробку и предупредили уже по дороге. По самой работе замечаний у меня нет.' },
    { n: 'Юлия Р.', o: 'Поддерживающая уборка раз в неделю', h: 'по 3 часа', d: 'постоянный клиент', r: 5,
      t: 'Третий месяц приходит один и тот же клинер, поэтому объяснять ничего не нужно. Ключи оставляю у консьержа, отчёт с фотографиями приходит в мессенджер. Мне важна именно эта предсказуемость.' },
    { n: 'Сергей Н.', o: 'Химчистка дивана и двух кресел', h: 'работали 2 часа', d: 'март', r: 5,
      t: 'Светлый диван после кота и детей выглядел тяжело. Мастер сначала проверил ткань на незаметном участке, потом почистил экстрактором. Высох за ночь, пятна от сока ушли полностью.' }
  ];

  var SHOWN = 4;

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

  function init(root) {
    if (root.__vb) return; root.__vb = 1;
    var grid = root.querySelector('#vbopu-grid'), more = root.querySelector('#vbopu-more');
    var avgEl = root.querySelector('#vbopu-avg'), topStars = root.querySelector('#vbopu-stars');

    function stars(rate) {
      var s = '';
      for (var j = 0; j < 5; j++) {
        s += '<svg viewBox="0 0 20 20"' + (j < rate ? ' class="vbopu-on"' : '') + ' aria-hidden="true" focusable="false">' +
          '<path d="M10 1.6l2.5 5.1 5.6.8-4.1 4 1 5.6L10 14.4l-5 2.7 1-5.6-4.1-4 5.6-.8z"/><\/svg>';
      }
      return s;
    }

    var sum = 0;
    for (var k = 0; k < REVIEWS.length; k++) sum += REVIEWS[k].r;
    var avg = sum / REVIEWS.length;
    avgEl.textContent = avg.toFixed(1).replace('.', ',');
    topStars.innerHTML = stars(Math.round(avg));
    topStars.setAttribute('aria-label', 'Средняя оценка ' + avg.toFixed(1).replace('.', ',') + ' из 5');

    var html = '';
    for (var m = 0; m < REVIEWS.length; m++) {
      var v = REVIEWS[m];
      html += '<article class="vbopu-card' + (m >= SHOWN ? ' vbopu-card--hid' : '') + '">' +
        '<div class="vbopu-card__top"><span class="vbopu-ava">' + v.n.charAt(0) + '<\/span>' +
        '<span><b class="vbopu-card__n">' + v.n + '<\/b><span class="vbopu-card__d">' + v.d + '<\/span><\/span>' +
        '<span class="vbopu-stars" role="img" aria-label="Оценка ' + v.r + ' из 5">' + stars(v.r) + '<\/span><\/div>' +
        '<div class="vbopu-tags"><span>' + v.o + '<\/span><span>' + v.h + '<\/span><\/div>' +
        '<p>' + v.t + '<\/p><\/article>';
    }
    grid.innerHTML = html;

    if (REVIEWS.length <= SHOWN) { more.parentNode.style.display = 'none'; return; }
    more.addEventListener('click', function () {
      var hid = grid.querySelectorAll('.vbopu-card--hid');
      for (var q = 0; q < hid.length; q++) hid[q].className = 'vbopu-card';
      more.parentNode.style.display = 'none';
    });
  }
})();
</script>

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

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

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

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

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

Где в кодеЗа что отвечает
массив REVIEWS в начале скриптаимя, объект, время работы, дата, оценка и текст отзыва
переменная SHOWNсколько плиток видно до нажатия кнопки
подпись про число анкет в разметкеколичество собранных анкет и период
--acc и --star в стиляхцвет средней оценки и заливка звёзд рейтинга

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

Отзыв про уборку убеждает, когда рядом стоит объект и время работы: двушка после ремонта за семь часов читается иначе, чем безымянная похвала. В каждой плитке выводятся имя, дата или пометка о постоянном клиенте, объект, время работы, оценка звёздами и текст. Звёзды нарисованы векторно прямо в скрипте, поэтому картинки не подгружаются и рейтинг остаётся резким на любом экране.

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

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

  • Скрипт закрашивает целые звёзды по числу в поле r. Для половинных значений проще оставить целую оценку в звёздах, а точную цифру вынести в подпись рядом с именем, как сделано для средней оценки сверху.

  • Поставьте переменной SHOWN значение больше длины массива REVIEWS. Кнопка под сеткой скроется автоматически, потому что скрытых плиток не останется.

  • Нет, блок работает без внешних запросов и хранит тексты внутри себя. Это демонстрационное наполнение под замену: перенесите свои отзывы в массив, сохранив набор полей.

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

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

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

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

Ещё блоки для клининговых компаний

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

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