Отзывы заказчиков о строительстве дома
Плитки отзывов, где рядом с текстом вынесены объект, срок стройки и строка про смету. Сверху стоит фильтр по материалу стен: каркас, газобетон, брус.
<section class="vbozd">
<div class="vbozd-wrap">
<div class="vbozd-head">
<div>
<h2 class="vbozd-h2">Что говорят заказчики после новоселья</h2>
<p class="vbozd-lead">Собираем отзывы через полгода после передачи ключей, когда дом уже прошёл первую зиму. Указываем, что построили, сколько это заняло и попали ли в смету.</p>
</div>
<div class="vbozd-score">
<b>32</b>
<span>дома сдали за прошлый сезон, 29 из них в срок по договору</span>
</div>
</div>
<div class="vbozd-tabs" id="vbozd-tabs"></div>
<div class="vbozd-grid" id="vbozd-grid"></div>
</div>
</section>
<style>
.vbozd, .vbozd *, .vbozd *::before, .vbozd *::after { box-sizing: border-box; }
.vbozd {
--acc: #3f6b52; --acc-dark: #325741; --ink: #1d211e; --muted: #666e68; --line: #e0e5e0; --soft: #f2f6f2; --warn: #a8611f;
--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;
}
.vbozd-wrap { max-width: 1240px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 40px); }
.vbozd-head { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, .65fr); gap: clamp(20px, 3vw, 44px);
align-items: end; margin-bottom: clamp(24px, 3vw, 38px); }
.vbozd-h2 { font-family: var(--fh); font-size: clamp(26px, 3.4vw, 42px); line-height: 1.1; font-weight: 700; letter-spacing: -.022em; margin: 0 0 12px; }
.vbozd-lead { font-size: 16px; line-height: 1.6; color: var(--muted); margin: 0; max-width: 40em; }
.vbozd-score { display: flex; align-items: center; gap: 16px; background: var(--soft); border-radius: 18px; padding: 20px 22px; }
.vbozd-score b { font-family: var(--fh); font-size: 44px; line-height: 1; font-weight: 700; color: var(--acc); }
.vbozd-score span { font-size: 13.5px; line-height: 1.45; color: var(--muted); }
.vbozd-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
.vbozd-tab { border: 1.5px solid var(--line); margin: 0; padding: 10px 18px; -webkit-appearance: none; appearance: none;
font: inherit; font-size: 14.5px; cursor: pointer; border-radius: 999px;
background: #fff !important; color: var(--ink) !important; transition: .18s ease; }
.vbozd-tab:hover { border-color: var(--acc); }
.vbozd-tab--on, .vbozd-tab--on:hover { background: var(--acc) !important; border-color: var(--acc); color: #fff !important; }
.vbozd-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; align-items: start; }
.vbozd-card { border: 1px solid var(--line); border-radius: 18px; padding: 22px 24px; }
.vbozd-card__top { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.vbozd-ava { flex: 0 0 44px; width: 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); }
.vbozd-card__n { display: block; font-size: 15.5px; font-weight: 600; }
.vbozd-card__o { display: block; font-size: 12.5px; color: var(--muted); margin-top: 3px; }
.vbozd-meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-bottom: 14px; }
.vbozd-meta div { background: var(--soft); border-radius: 11px; padding: 10px 13px; }
.vbozd-meta span { display: block; font-size: 11.5px; color: var(--muted); }
.vbozd-meta b { display: block; font-size: 13.5px; font-weight: 600; margin-top: 3px; }
.vbozd-meta b.vbozd-over { color: var(--warn); }
.vbozd-card p { margin: 0; font-size: 14.8px; line-height: 1.68; color: var(--muted); }
.vbozd-empty { grid-column: 1 / -1; font-size: 15px; color: var(--muted); padding: 22px 0; margin: 0; }
@media (max-width: 900px) { .vbozd-head { grid-template-columns: minmax(0, 1fr); align-items: start; } }
@media (max-width: 400px) { .vbozd-meta { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) { .vbozd * { transition: none !important; } }
</style>
<script>
(function () {
/* ── ОТЗЫВЫ: mat это материал для фильтра, fit это попадание в смету ── */
var REVIEWS = [
{ name: 'Андрей и Мария Ковалёвы', mat: 'frame', obj: 'Каркасный дом 120 м², посёлок Ольгино',
term: '4 месяца', fit: 'Смета без изменений',
text: 'Договорились в феврале, ключи получили в июне. Раз в неделю приезжал наш инженер и присылал фотографии по этапам, поэтому мы спокойно жили в городе и не караулили стройку. Итог совпал со сметой до рубля, доплачивали только за розетки сверх проекта.' },
{ name: 'Сергей Литвинов', mat: 'gas', obj: 'Газобетон 160 м², Всеволожский район',
term: '7 месяцев', fit: 'Смета выросла на 4%',
text: 'Геология показала глину с высокой водой, поэтому вместо ленты делали плиту. Разницу посчитали заранее и показали расчёт, я согласовал письменно. Дом прошёл вторую зиму, по стенам трещин нет, счёт за газ за январь вышел 4 700 рублей.' },
{ name: 'Ольга Терентьева', mat: 'brus', obj: 'Дом из бруса 96 м², Приозерское шоссе',
term: '5 месяцев', fit: 'Смета без изменений',
text: 'Хотела деревянный дом и боялась историй про усадку. Бригадир объяснил, почему чистовые работы начнём через полгода, и мы заложили это в график сразу. Год прошёл, зазоры компенсировались винтами, двери открываются нормально.' },
{ name: 'Дмитрий Савчук', mat: 'gas', obj: 'Газобетон 186 м² с гаражом, Токсово',
term: '9 месяцев', fit: 'Смета выросла на 2%',
text: 'Строили с зимним перерывом на кладку. Понравилось, что каждый этап закрывали актом и я платил после приёмки. Один раз ошиблись с высотой проёма под входную дверь, переделали за свой счёт за три дня и не спорили.' },
{ name: 'Ирина и Павел Носовы', mat: 'frame', obj: 'Каркасный дом 78 м², Синявино',
term: '3 месяца', fit: 'Смета без изменений',
text: 'Бюджет был жёсткий, поэтому выбрали тёплый контур и отделку делали сами следующей весной. Нам подробно расписали, что входит в контур и чего ждать дальше. Разводку электрики оставили с запасом под будущую кухню.' },
{ name: 'Виктор Хомяков', mat: 'brus', obj: 'Брус 132 м², Лужский район',
term: '6 месяцев', fit: 'Смета выросла на 3%',
text: 'Участок в 90 километрах от города, доставка бруса вышла дороже расчёта, о чём предупредили до подписания. По самой сборке вопросов нет, венцы легли ровно, щелей после первой зимы не появилось. Документы передали полным комплектом.' }
];
/* ── ФИЛЬТРЫ ── */
var TABS = [
{ k: 'all', t: 'Все дома' },
{ k: 'frame', t: 'Каркас' },
{ k: 'gas', t: 'Газобетон' },
{ k: 'brus', t: 'Брус' }
];
var roots = document.querySelectorAll('.vbozd');
for (var i = 0; i < roots.length; i++) init(roots[i]);
function init(root) {
if (root.__vb) return; root.__vb = 1;
var tabsBox = root.querySelector('#vbozd-tabs'), grid = root.querySelector('#vbozd-grid');
var cur = 'all';
var th = '';
for (var t = 0; t < TABS.length; t++) {
th += '<button type="button" class="vbozd-tab' + (TABS[t].k === cur ? ' vbozd-tab--on' : '') +
'" data-k="' + TABS[t].k + '">' + TABS[t].t + '<\/button>';
}
tabsBox.innerHTML = th;
var btns = tabsBox.querySelectorAll('.vbozd-tab');
for (var b = 0; b < btns.length; b++) bind(btns[b]);
function bind(btn) {
btn.addEventListener('click', function () {
cur = btn.getAttribute('data-k');
for (var j = 0; j < btns.length; j++) {
btns[j].className = 'vbozd-tab' + (btns[j] === btn ? ' vbozd-tab--on' : '');
}
draw();
});
}
function draw() {
var html = '', shown = 0, r;
for (var n = 0; n < REVIEWS.length; n++) {
r = REVIEWS[n];
if (cur !== 'all' && r.mat !== cur) continue;
shown++;
html += '<article class="vbozd-card"><div class="vbozd-card__top">' +
'<span class="vbozd-ava">' + r.name.charAt(0) + '<\/span>' +
'<span><b class="vbozd-card__n">' + r.name + '<\/b>' +
'<span class="vbozd-card__o">' + r.obj + '<\/span><\/span><\/div>' +
'<div class="vbozd-meta"><div><span>Срок стройки<\/span><b>' + r.term + '<\/b><\/div>' +
'<div><span>Бюджет<\/span><b class="' + (r.fit.indexOf('выросла') > -1 ? 'vbozd-over' : '') + '">' + r.fit + '<\/b><\/div><\/div>' +
'<p>' + r.text + '<\/p><\/article>';
}
if (!shown) html = '<p class="vbozd-empty">По этому материалу отзывов пока нет.<\/p>';
grid.innerHTML = html;
}
draw();
}
})();
</script> Вставляется целиком в блок T123 «HTML-код». Внутри уже есть стили и скрипт, подключать ничего не нужно.
Как вставить блок в Tilda
- Скопируйте кодКнопка «Скопировать код» выше кладёт всё содержимое в буфер обмена.
- Добавьте блок T123В редакторе страницы: «Библиотека блоков» → «Другое» → T123 «HTML-код».
- Вставьте и сохранитеНажмите «Контент», вставьте код в поле, сохраните и обновите страницу.
- ОпубликуйтеВ превью скрипты Tilda работают не всегда — проверяйте на опубликованной странице.
Подробная инструкция с граблями — как вставить вайб-блок в Tilda.
Что менять под себя
| Где в коде | За что отвечает |
|---|---|
массив REVIEWS | отзывы: имя, объект, срок стройки, попадание в смету, текст |
массив TABS | кнопки фильтра по материалу стен |
цифру в плашке сверху | сколько домов сдали за сезон и сколько из них в срок |
--acc и --warn | цвет активного фильтра и подсветка превышения сметы |
Отзывы заказчиков о доме: зачем он нужен
Отзыв о стройке ценен подробностями: что именно построили, за сколько месяцев и попал ли итог в смету. В карточке эти три вещи вынесены отдельно от текста, поэтому их видно ещё до чтения. Отзывы с превышением сметы помечены другим цветом и оставлены в подборке: они добавляют доверия остальным. Плитки перестраиваются под ширину экрана и на телефоне идут одной колонкой.
Над плитками стоит фильтр по материалу стен, чтобы посетитель с каркасным домом читал именно про каркас. Все отзывы лежат в массиве REVIEWS в начале скрипта: имя, ключ материала, объект, срок, строка про смету и текст. Кнопки фильтра строятся из массива TABS, поэтому добавить материал это дописать одну строку. Если по выбранному фильтру записей нет, блок покажет короткое сообщение вместо пустой сетки.
Вопросы по этому блоку
-
Допишите объект в массив REVIEWS. Поле с материалом должно совпадать с ключом одной из кнопок фильтра, иначе отзыв будет виден только на вкладке со всеми домами.
-
Да. Оставьте в массиве TABS один элемент с ключом all, тогда останется одна кнопка. Либо скройте контейнер фильтра стилем display none, сетка отзывов продолжит работать.
-
Скрипт берёт первую букву из поля с именем. Если нужны фотографии, замените элемент с классом vbozd-ava на картинку, загруженную в файлы Tilda.
-
Да. Код на этой странице копируется целиком, без регистрации и подписки. Указывать авторство не нужно, использовать можно в коммерческих проектах.
-
Нет. Все классы внутри имеют собственный префикс vbozd, поэтому не пересекаются ни со стилями Tilda, ни с другими блоками. Скрипт привязан к своему элементу и запускается один раз, даже если блок вставлен дважды.
-
Раскладка перестраивается под узкие экраны, размеры заданы через clamp, поля ввода имеют шрифт 16 пикселей — iOS не будет зумить страницу при фокусе. Отдельной мобильной версии подключать не нужно.
Другие блоки отзывов
Ещё блоки для строительства домов
Собрать сайт целиком, а не по блокам
Дровосеки делают сайты на Tilda под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.