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