Блок отзывов клининговой компании для 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
- Скопируйте кодКнопка «Скопировать код» выше кладёт всё содержимое в буфер обмена.
- Добавьте блок T123В редакторе страницы: «Библиотека блоков» → «Другое» → T123 «HTML-код».
- Вставьте и сохранитеНажмите «Контент», вставьте код в поле, сохраните и обновите страницу.
- ОпубликуйтеВ превью скрипты Tilda работают не всегда — проверяйте на опубликованной странице.
Подробная инструкция с граблями — как вставить вайб-блок в Tilda.
Что менять под себя
| Где в коде | За что отвечает |
|---|---|
массив REVIEWS в начале скрипта | имя, объект, время работы, дата, оценка и текст отзыва |
переменная SHOWN | сколько плиток видно до нажатия кнопки |
подпись про число анкет в разметке | количество собранных анкет и период |
--acc и --star в стилях | цвет средней оценки и заливка звёзд рейтинга |
Отзывы после уборки: зачем он нужен
Отзыв про уборку убеждает, когда рядом стоит объект и время работы: двушка после ремонта за семь часов читается иначе, чем безымянная похвала. В каждой плитке выводятся имя, дата или пометка о постоянном клиенте, объект, время работы, оценка звёздами и текст. Звёзды нарисованы векторно прямо в скрипте, поэтому картинки не подгружаются и рейтинг остаётся резким на любом экране.
Средний балл считается по массиву отзывов, вручную его править не нужно: добавили отзыв, цифра пересчиталась. Первые четыре плитки видны сразу, остальные раскрывает кнопка под сеткой, а если отзывов мало, кнопка скрывается сама. Сетка построена на автоподборе колонок и на телефоне переходит в одну колонку.
Вопросы по этому блоку
-
Скрипт закрашивает целые звёзды по числу в поле r. Для половинных значений проще оставить целую оценку в звёздах, а точную цифру вынести в подпись рядом с именем, как сделано для средней оценки сверху.
-
Поставьте переменной SHOWN значение больше длины массива REVIEWS. Кнопка под сеткой скроется автоматически, потому что скрытых плиток не останется.
-
Нет, блок работает без внешних запросов и хранит тексты внутри себя. Это демонстрационное наполнение под замену: перенесите свои отзывы в массив, сохранив набор полей.
-
Да. Код на этой странице копируется целиком, без регистрации и подписки. Указывать авторство не нужно, использовать можно в коммерческих проектах.
-
Нет. Все классы внутри имеют собственный префикс vbopu, поэтому не пересекаются ни со стилями Tilda, ни с другими блоками. Скрипт привязан к своему элементу и запускается один раз, даже если блок вставлен дважды.
-
Раскладка перестраивается под узкие экраны, размеры заданы через clamp, поля ввода имеют шрифт 16 пикселей — iOS не будет зумить страницу при фокусе. Отдельной мобильной версии подключать не нужно.
Другие блоки отзывов
Ещё блоки для клининговых компаний
Собрать сайт целиком, а не по блокам
Дровосеки делают сайты на Tilda под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.