Задать вопрос директору
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 под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса. Как это выглядит для ниши «Клининг», видно на отдельной странице.