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

Блок отзывов пациентов с рейтингом по критериям

Слева сводный рейтинг по четырём критериям с полосами заполнения, справа — отзывы с услугой и датой. Полосы рисуются при появлении блока.

Живое демо — блок работает прямо здесь

Код блока

<section class="vbotp">
  <div class="vbotp-wrap">
    <div class="vbotp-side">
      <h2 class="vbotp-h2">Оценки пациентов</h2>
      <p class="vbotp-lead">Собираем анкету после каждого приёма. Ниже — среднее по четырём критериям за последние 12 месяцев.</p>

      <div class="vbotp-total">
        <b id="vbotp-avg">4,8</b>
        <span>средняя оценка<br>по 1 284 анкетам</span>
      </div>

      <ul class="vbotp-crit" id="vbotp-crit"></ul>
    </div>

    <div class="vbotp-list" id="vbotp-list"></div>
  </div>
</section>

<style>
.vbotp, .vbotp *, .vbotp *::before, .vbotp *::after { box-sizing: border-box; }
.vbotp {
  --acc: #1c7f8c; --ink: #1d2b2e; --muted: #5f7276; --line: #dfe8e9; --soft: #f2f7f7;
  --f: var(--t-text-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif);
  --fh: var(--t-headline-font, var(--f));
  background: #fff; color: var(--ink); font-family: var(--f); padding: clamp(36px, 5vw, 80px) 20px;
}
.vbotp-wrap { max-width: 1240px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 40px);
  display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: clamp(26px, 4vw, 56px); align-items: start; }
.vbotp-h2 { font-family: var(--fh); font-size: clamp(26px, 3.4vw, 42px); line-height: 1.1; font-weight: 700; letter-spacing: -.02em; margin: 0 0 12px; }
.vbotp-lead { font-size: 16px; line-height: 1.6; color: var(--muted); margin: 0 0 26px; }

.vbotp-total { display: flex; align-items: center; gap: 16px; background: var(--soft); border-radius: 18px; padding: 20px 22px; margin-bottom: 24px; }
.vbotp-total b { font-family: var(--fh); font-size: 46px; line-height: 1; font-weight: 700; color: var(--acc); }
.vbotp-total span { font-size: 13.5px; line-height: 1.45; color: var(--muted); }

.vbotp-crit { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; }
.vbotp-crit__top { display: flex; justify-content: space-between; font-size: 14px; margin-bottom: 7px; }
.vbotp-crit__top b { font-weight: 600; }
.vbotp-crit__bar { height: 6px; border-radius: 6px; background: var(--soft); overflow: hidden; }
.vbotp-crit__bar i { display: block; height: 100%; width: 0; border-radius: 6px; background: var(--acc); transition: width 1s cubic-bezier(.22,1,.36,1); }

.vbotp-list { display: grid; gap: 14px; }
.vbotp-card { border: 1px solid var(--line); border-radius: 18px; padding: 22px 24px; }
.vbotp-card__top { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.vbotp-ava { flex: 0 0 42px; width: 42px; height: 42px; border-radius: 50%; background: var(--soft); display: flex; align-items: center;
  justify-content: center; font-size: 15px; font-weight: 600; color: var(--acc); }
.vbotp-card__n { display: block; font-size: 15px; font-weight: 600; }
.vbotp-card__m { display: block; font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.vbotp-card__r { margin-left: auto; font-family: var(--fh); font-size: 16px; font-weight: 700; color: var(--acc); }
.vbotp-card p { margin: 0; font-size: 15px; line-height: 1.65; color: var(--muted); }

@media (max-width: 900px) { .vbotp-wrap { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) { .vbotp-crit__bar i { transition: none !important; } }
</style>

<script>
(function () {
  /* ── КРИТЕРИИ: балл от 0 до 5 ── */
  var CRITERIA = [
    { name: 'Работа врача', val: 4.9 },
    { name: 'Администраторы и запись', val: 4.8 },
    { name: 'Чистота и комфорт', val: 4.9 },
    { name: 'Цена и качество', val: 4.6 }
  ];

  /* ── ОТЗЫВЫ ── */
  var REVIEWS = [
    { name: 'Елена П.', service: 'Имплантация, 2 импланта', date: 'февраль', rate: 5,
      text: 'Боялась операции полгода, оттягивала как могла. Врач показал КТ на экране, объяснил, что и почему будет делать, и предупредил про отёк заранее. Всё прошло ровно так, как он описал, — никаких сюрпризов, и это оказалось важнее анестезии.' },
    { name: 'Максим Т.', service: 'Лечение каналов', date: 'март', rate: 5,
      text: 'Пришёл с зубом, который в другой клинике предложили удалять. Здесь перелечили каналы под микроскопом, зуб живой уже второй год. Отдельно ценю, что назвали окончательную сумму сразу и она не выросла.' },
    { name: 'Ольга С.', service: 'Гигиена и отбеливание', date: 'январь', rate: 5,
      text: 'Впервые за много лет гигиена без боли. Гигиенист работал медленно, спрашивал про чувствительность и не пытался продать мне сверху ещё три процедуры. Записалась сразу на следующий раз.' },
    { name: 'Игорь В.', service: 'Брекеты', date: 'декабрь', rate: 4,
      text: 'Лечение идёт год, результат уже виден. Единственное, к чему придирался, — пару раз сдвигали время приёма. Предупреждали заранее, но всё равно неудобно. По самой работе вопросов нет.' },
    { name: 'Наталья К.', service: 'Детский приём', date: 'март', rate: 5,
      text: 'Сына четырёх лет привели после неудачного опыта в поликлинике — заходил в кабинет со слезами. Первый визит был просто знакомством, ничего не делали. На третий он сам залез в кресло. Это дорогого стоит.' }
  ];

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

  function init(root) {
    if (root.__vb) return; root.__vb = 1;
    var critBox = root.querySelector('#vbotp-crit'), listBox = root.querySelector('#vbotp-list'), avgEl = root.querySelector('#vbotp-avg');

    var avg = CRITERIA.reduce(function (s, c) { return s + c.val; }, 0) / CRITERIA.length;
    avgEl.textContent = avg.toFixed(1).replace('.', ',');

    critBox.innerHTML = CRITERIA.map(function (c) {
      return '<li><div class="vbotp-crit__top"><span>' + c.name + '<\/span><b>' + c.val.toFixed(1).replace('.', ',') + '<\/b><\/div>' +
        '<div class="vbotp-crit__bar"><i data-w="' + (c.val / 5 * 100) + '"><\/i><\/div><\/li>';
    }).join('');

    listBox.innerHTML = REVIEWS.map(function (r) {
      return '<article class="vbotp-card"><div class="vbotp-card__top">' +
        '<span class="vbotp-ava">' + r.name.charAt(0) + '<\/span>' +
        '<span><b class="vbotp-card__n">' + r.name + '<\/b><span class="vbotp-card__m">' + r.service + ' · ' + r.date + '<\/span><\/span>' +
        '<span class="vbotp-card__r">' + r.rate + ',0<\/span><\/div>' +
        '<p>' + r.text + '<\/p><\/article>';
    }).join('');

    var bars = critBox.querySelectorAll('.vbotp-crit__bar i');
    function fill() { bars.forEach(function (b, i) { setTimeout(function () { b.style.width = b.dataset.w + '%'; }, i * 110); }); }

    if (!('IntersectionObserver' in window)) { fill(); return; }
    var io = new IntersectionObserver(function (es) {
      es.forEach(function (e) { if (e.isIntersecting) { fill(); io.disconnect(); } });
    }, { rootMargin: '0px 0px -10% 0px' });
    io.observe(critBox);
    setTimeout(fill, 2500);
  }
})();
</script>

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

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

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

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

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

Где в кодеЗа что отвечает
массив CRITERIAназвания критериев и баллы
массив REVIEWSсами отзывы: имя, текст, услуга, дата
--accцвет полос и общей оценки

Отзывы пациентов с рейтингом: зачем он нужен

Один общий балл «4,9 из 5» ни о чём не говорит. Разбивка по критериям — врач, администраторы, чистота, цена-качество — выглядит честнее и заодно отвечает на разные страхи пациентов.

Полосы заполняются один раз, когда блок попадает в поле зрения, и больше не анимируются при повторной прокрутке. Это отличает аккуратный блок от навязчивого.

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

  • Из своих источников: карточка организации в картах, внутренний опрос, анкета после приёма. Блок ничего не подтягивает автоматически — цифры проставляются руками, зато вы не зависите от чужого API.

  • Да, добавьте элемент в массив CRITERIA — полоса появится сама, высота левой колонки подстроится.

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

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

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

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

Ещё блоки для медицины и стоматологии

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

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