Калькулятор ремонта квартиры для Tilda
Считает смету по площади, типу ремонта и набору дополнительных работ. Показывает не одну цифру, а разбивку по статьям — так возражение «почему так дорого» снимается прямо в калькуляторе.
<section class="vbkrk">
<div class="vbkrk-wrap">
<h2 class="vbkrk-h2">Калькулятор ремонта квартиры</h2>
<p class="vbkrk-lead">Двигайте параметры — смета пересчитывается сразу. Итог разложен по статьям, чтобы было видно, из чего складывается цена.</p>
<div class="vbkrk-grid">
<div class="vbkrk-controls">
<div class="vbkrk-ctl">
<div class="vbkrk-ctl__top"><span>Площадь квартиры</span><b id="vbkrk-area">54 м²</b></div>
<input type="range" id="vbkrk-range" min="18" max="200" step="1" value="54" aria-label="Площадь квартиры">
</div>
<div class="vbkrk-ctl">
<span class="vbkrk-ctl__lbl">Тип ремонта</span>
<div class="vbkrk-seg" id="vbkrk-types" role="radiogroup" aria-label="Тип ремонта"></div>
</div>
<div class="vbkrk-ctl">
<span class="vbkrk-ctl__lbl">Дополнительные работы</span>
<div class="vbkrk-extras" id="vbkrk-extras"></div>
</div>
<label class="vbkrk-urg">
<input type="checkbox" id="vbkrk-rush">
<span class="vbkrk-urg__box"></span>
<span>Сжатые сроки — работа в две смены <i>+18%</i></span>
</label>
</div>
<aside class="vbkrk-out">
<span class="vbkrk-out__lbl">Предварительная смета</span>
<strong class="vbkrk-out__sum" id="vbkrk-sum">810 000 ₽</strong>
<span class="vbkrk-out__m2" id="vbkrk-m2">15 000 ₽ за м²</span>
<ul class="vbkrk-rows" id="vbkrk-rows"></ul>
<div class="vbkrk-note">Расчёт предварительный. Точная смета составляется после замера и согласования материалов.</div>
<form class="vbkrk-form t-form js-form-proccess" role="form" action="#" method="POST"
data-vibeblock-form="true" data-formactiontype="2" data-error-popup="y" data-success-popup="y"
data-success-callback="vbkrkSuccess" data-inputbox=".vbkrk-inp, .vbkrk-consent-inp" novalidate>
<input type="hidden" name="formservices[]" value="HASH_EMAIL" class="js-formaction-services">
<input type="hidden" name="form_source" value="Калькулятор ремонта">
<input type="hidden" name="Raschet" id="vbkrk-hidden" value="">
<input type="tel" name="Phone" class="vbkrk-inp js-tilda-rule js-tilda-mask" data-tilda-req="1"
data-tilda-rule="phone" data-tilda-mask="+7 (999) 999-99-99" inputmode="tel" placeholder="+7 (___) ___-__-__">
<label class="vbkrk-consent">
<input type="checkbox" name="Privacy" value="Da" class="vbkrk-consent-inp js-tilda-rule" data-tilda-req="1">
<span class="vbkrk-consent__box"></span>
<span>Согласен с <a href="/policy" target="_blank" rel="noopener">политикой конфиденциальности</a></span>
</label>
<button type="submit" class="vbkrk-submit t-submit">Прислать смету в PDF</button>
</form>
</aside>
</div>
</div>
</section>
<style>
.vbkrk, .vbkrk *, .vbkrk *::before, .vbkrk *::after { box-sizing: border-box; }
.vbkrk {
--acc: #e8622a; --acc-dark: #cf5119; --ink: #1b1b1b; --muted: #6f6f6f;
--line: #e6e3df; --bg: #fff; --panel: #f6f4f1;
--f: var(--t-text-font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif);
--fh: var(--t-headline-font, var(--f));
background: var(--bg); color: var(--ink); font-family: var(--f); padding: clamp(36px, 5vw, 80px) 20px;
}
.vbkrk-wrap { max-width: 1240px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 40px); }
.vbkrk-h2 { font-family: var(--fh); font-size: clamp(26px, 3.4vw, 42px); line-height: 1.12; font-weight: 700; letter-spacing: -.02em; margin: 0 0 12px; }
.vbkrk-lead { font-size: 16px; line-height: 1.55; color: var(--muted); margin: 0 0 32px; max-width: 46em; }
.vbkrk-grid { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, .75fr); gap: clamp(20px, 3vw, 40px); align-items: start; }
.vbkrk-controls { background: var(--panel); border-radius: 22px; padding: clamp(20px, 2.6vw, 32px); }
.vbkrk-ctl { margin-bottom: 26px; }
.vbkrk-ctl__top { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 12px; font-size: 15px; color: var(--muted); }
.vbkrk-ctl__top b { font-family: var(--fh); font-size: 20px; color: var(--ink); }
.vbkrk-ctl__lbl { display: block; font-size: 15px; color: var(--muted); margin-bottom: 12px; }
.vbkrk input[type=range] { -webkit-appearance: none; appearance: none; width: 100%; height: 4px; border-radius: 4px; background: #ddd8d2; outline: none; }
.vbkrk input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 24px; height: 24px; border-radius: 50%;
background: var(--acc); border: 4px solid #fff; box-shadow: 0 1px 6px rgba(0,0,0,.22); cursor: pointer; }
.vbkrk input[type=range]::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: var(--acc); border: 3px solid #fff; cursor: pointer; }
.vbkrk-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.vbkrk-seg button { border: 1.5px solid var(--line); margin: 0; -webkit-appearance: none; appearance: none; font: inherit;
cursor: pointer; background: #fff !important; color: var(--ink) !important; border-radius: 12px; padding: 12px 10px; text-align: left; transition: .18s ease; }
.vbkrk-seg button b { display: block; font-size: 15px; font-weight: 600; }
.vbkrk-seg button i { display: block; font-style: normal; font-size: 12px; color: var(--muted); margin-top: 3px; }
.vbkrk-seg button:hover { border-color: #c8c2ba; }
.vbkrk-seg button[aria-checked="true"] { border-color: var(--acc); background: #fff8f4 !important; }
.vbkrk-seg button[aria-checked="true"] i { color: var(--acc); }
.vbkrk-extras { display: grid; gap: 8px; }
.vbkrk-chk { display: flex; align-items: center; gap: 10px; background: #fff; border: 1.5px solid var(--line); border-radius: 12px;
padding: 12px 14px; cursor: pointer; font-size: 15px; transition: border-color .18s ease; }
.vbkrk-chk:hover { border-color: #c8c2ba; }
.vbkrk-chk input { position: absolute; opacity: 0; width: 0; height: 0; }
.vbkrk-chk__box, .vbkrk-urg__box { flex: 0 0 18px; width: 18px; height: 18px; border: 1.5px solid #c9c5c0; border-radius: 5px; background: #fff; position: relative; }
.vbkrk-chk input:checked + .vbkrk-chk__box, .vbkrk-urg input:checked + .vbkrk-urg__box,
.vbkrk-consent input:checked + .vbkrk-consent__box { background: var(--acc); border-color: var(--acc); }
.vbkrk-chk input:checked + .vbkrk-chk__box::after, .vbkrk-urg input:checked + .vbkrk-urg__box::after,
.vbkrk-consent input:checked + .vbkrk-consent__box::after { content: ''; position: absolute; left: 5px; top: 1px; width: 5px; height: 10px;
border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }
.vbkrk-chk__price { margin-left: auto; color: var(--muted); font-size: 14px; white-space: nowrap; }
.vbkrk-urg { display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 15px; }
.vbkrk-urg input { position: absolute; opacity: 0; width: 0; height: 0; }
.vbkrk-urg i { font-style: normal; color: var(--acc); font-weight: 600; }
.vbkrk-out { background: #191614; color: #fff; border-radius: 22px; padding: clamp(20px, 2.6vw, 30px); position: sticky; top: 20px; }
.vbkrk-out__lbl { display: block; font-size: 13px; color: #a49c96; }
.vbkrk-out__sum { display: block; font-family: var(--fh); font-size: clamp(30px, 3.4vw, 42px); line-height: 1.1; font-weight: 700; margin: 6px 0 4px; }
.vbkrk-out__m2 { display: block; font-size: 14px; color: #a49c96; }
.vbkrk-rows { list-style: none; margin: 20px 0 0; padding: 18px 0 0; border-top: 1px solid rgba(255,255,255,.14); display: grid; gap: 11px; }
.vbkrk-rows li { display: flex; justify-content: space-between; gap: 14px; font-size: 14px; color: #d6d0cb; }
.vbkrk-rows li b { color: #fff; font-weight: 600; white-space: nowrap; }
.vbkrk-note { margin: 18px 0; font-size: 12px; line-height: 1.5; color: #8d857f; }
.vbkrk-inp { width: 100%; height: 52px; padding: 0 16px; font: inherit; font-size: 16px; -webkit-appearance: none; appearance: none;
border: 1px solid rgba(255,255,255,.2); border-radius: 10px; background: rgba(255,255,255,.06); color: #fff; }
.vbkrk-inp::placeholder { color: #8d857f; }
.vbkrk-inp:focus { outline: 2px solid var(--acc); outline-offset: -2px; }
.vbkrk-consent { display: flex; align-items: flex-start; gap: 9px; margin: 12px 0 14px; cursor: pointer; font-size: 12px; line-height: 1.45; color: #a49c96; }
.vbkrk-consent input { position: absolute; opacity: 0; width: 0; height: 0; }
.vbkrk-consent__box { flex: 0 0 18px; width: 18px; height: 18px; margin-top: 1px; border: 1.5px solid #5d554f; border-radius: 5px; position: relative; }
.vbkrk-consent a, .vbkrk-consent a:link, .vbkrk-consent a:visited, .vbkrk-consent a:hover, .vbkrk-consent a:active, .vbkrk-consent a:focus {
color: #fff !important; text-decoration: underline !important; }
.vbkrk-submit { width: 100%; min-height: 54px; border: 0; margin: 0; -webkit-appearance: none; appearance: none; font: inherit;
font-size: 16px; font-weight: 600; cursor: pointer; border-radius: 10px; background: var(--acc) !important; color: #fff !important; transition: background .2s ease; }
.vbkrk-submit:hover { background: var(--acc-dark) !important; }
.vbkrk-done { text-align: center; padding: 22px 6px; }
.vbkrk-done b { display: block; font-size: 18px; margin-bottom: 6px; }
.vbkrk-done span { font-size: 13px; color: #a49c96; }
@media (max-width: 900px) { .vbkrk-grid { grid-template-columns: minmax(0, 1fr); } .vbkrk-out { position: static; } }
@media (max-width: 560px) { .vbkrk-seg { grid-template-columns: minmax(0, 1fr); } }
@media (prefers-reduced-motion: reduce) { .vbkrk * { transition: none !important; } }
</style>
<script>
(function () {
/* ── ПРАЙС: цена за м² по типу ремонта ── */
var RATES = {
cosmetic: { name: 'Косметический', hint: 'от 8 500 ₽/м²', rate: 8500 },
capital: { name: 'Капитальный', hint: 'от 15 000 ₽/м²', rate: 15000 },
design: { name: 'Дизайнерский', hint: 'от 24 000 ₽/м²', rate: 24000 }
};
/* ── ДОП-РАБОТЫ: per — за м², one — разово ── */
var EXTRAS = [
{ id: 'plumb', name: 'Замена сантехники и разводка', price: 68000, mode: 'one' },
{ id: 'elec', name: 'Полная замена электрики', price: 1400, mode: 'per' },
{ id: 'floor', name: 'Стяжка и тёплый пол', price: 2300, mode: 'per' },
{ id: 'door', name: 'Межкомнатные двери, 4 шт.', price: 52000, mode: 'one' }
];
var RUSH = 0.18; /* надбавка за сжатые сроки */
var SHARE = { rough: .38, finish: .42, mat: .20 }; /* доли: черновая, чистовая, материалы */
var roots = document.querySelectorAll('.vbkrk');
for (var i = 0; i < roots.length; i++) init(roots[i]);
function init(root) {
if (root.__vb) return; root.__vb = 1;
var state = { area: 54, type: 'capital', extras: {}, rush: false };
var elArea = root.querySelector('#vbkrk-area'), elRange = root.querySelector('#vbkrk-range');
var elTypes = root.querySelector('#vbkrk-types'), elExtras = root.querySelector('#vbkrk-extras');
var elRush = root.querySelector('#vbkrk-rush'), elSum = root.querySelector('#vbkrk-sum');
var elM2 = root.querySelector('#vbkrk-m2'), elRows = root.querySelector('#vbkrk-rows'), elHid = root.querySelector('#vbkrk-hidden');
Object.keys(RATES).forEach(function (k) {
var b = document.createElement('button');
b.type = 'button'; b.setAttribute('role', 'radio');
b.setAttribute('aria-checked', k === state.type ? 'true' : 'false');
b.innerHTML = '<b>' + RATES[k].name + '<\/b><i>' + RATES[k].hint + '<\/i>';
b.addEventListener('click', function () {
state.type = k;
elTypes.querySelectorAll('button').forEach(function (x) { x.setAttribute('aria-checked', 'false'); });
b.setAttribute('aria-checked', 'true'); render();
});
elTypes.appendChild(b);
});
EXTRAS.forEach(function (ex) {
var l = document.createElement('label');
l.className = 'vbkrk-chk';
l.innerHTML = '<input type="checkbox"><span class="vbkrk-chk__box"><\/span><span>' + ex.name + '<\/span>' +
'<span class="vbkrk-chk__price">' + (ex.mode === 'per' ? fmt(ex.price) + ' ₽/м²' : fmt(ex.price) + ' ₽') + '<\/span>';
l.querySelector('input').addEventListener('change', function () { state.extras[ex.id] = this.checked; render(); });
elExtras.appendChild(l);
});
elRange.addEventListener('input', function () { state.area = +this.value; render(); });
elRush.addEventListener('change', function () { state.rush = this.checked; render(); });
function fmt(n) { return String(Math.round(n)).replace(/\B(?=(\d{3})+(?!\d))/g, ' '); }
function render() {
var base = state.area * RATES[state.type].rate;
var extra = 0;
EXTRAS.forEach(function (ex) { if (state.extras[ex.id]) extra += ex.mode === 'per' ? ex.price * state.area : ex.price; });
var total = base + extra;
if (state.rush) total = total * (1 + RUSH);
elArea.textContent = state.area + ' м²';
elSum.textContent = fmt(total) + ' ₽';
elM2.textContent = fmt(total / state.area) + ' ₽ за м²';
var rows = [
['Черновые работы', base * SHARE.rough],
['Чистовая отделка', base * SHARE.finish],
['Материалы, ориентир', base * SHARE.mat]
];
if (extra) rows.push(['Дополнительные работы', extra]);
if (state.rush) rows.push(['Надбавка за сроки', (base + extra) * RUSH]);
elRows.innerHTML = rows.map(function (r) {
return '<li><span>' + r[0] + '<\/span><b>' + fmt(r[1]) + ' ₽<\/b><\/li>';
}).join('');
if (elHid) elHid.value = state.area + ' м², ' + RATES[state.type].name + ', итого ' + fmt(total) + ' ₽';
}
render();
var form = root.querySelector('.vbkrk-form');
if (form && !form.__b) {
form.__b = 1;
form.addEventListener('submit', function (e) {
e.preventDefault();
var btn = form.querySelector('button[type="submit"], .t-submit');
if (btn && typeof window.t_forms__initBtnClick === 'function') {
try { window.t_forms__initBtnClick({ target: btn, srcElement: btn, preventDefault: function () {} }); } catch (_) {}
}
});
}
if (!window.vbkrkSuccess) {
window.vbkrkSuccess = function (f) {
try { f.innerHTML = '<div class="vbkrk-done"><b>Смета уходит к вам<\/b><span>Пришлём расчёт и перезвоним, чтобы уточнить детали.<\/span><\/div>'; } catch (e) {}
};
}
}
})();
</script> Вставляется целиком в блок T123 «HTML-код». Внутри уже есть стили и скрипт, подключать ничего не нужно. В форме замените HASH_EMAIL на хеш приёмника из Tilda → Site Settings → Forms.
Как вставить блок в Tilda
- Скопируйте кодКнопка «Скопировать код» выше кладёт всё содержимое в буфер обмена.
- Добавьте блок T123В редакторе страницы: «Библиотека блоков» → «Другое» → T123 «HTML-код».
- Вставьте и сохранитеНажмите «Контент», вставьте код в поле, сохраните и обновите страницу.
- ОпубликуйтеВ превью скрипты Tilda работают не всегда — проверяйте на опубликованной странице.
Подробная инструкция с граблями — как вставить вайб-блок в Tilda.
Что менять под себя
| Где в коде | За что отвечает |
|---|---|
объект RATES в начале скрипта | цены за м² для косметического, капитального и дизайнерского ремонта |
массив EXTRAS | список доп-работ и их стоимость |
--acc | акцентный цвет ползунков и итоговой суммы |
текст в блоке итога | подпись под суммой и дисклеймер |
Калькулятор ремонта квартиры: зачем он нужен
Обычный калькулятор выдаёт итог и оставляет человека наедине с вопросом, из чего он сложился. Здесь итог раскладывается на черновые работы, чистовую отделку, материалы и доп-услуги — посетитель видит логику и доверяет цифре.
Все коэффициенты вынесены в один объект в начале скрипта: тип ремонта, стоимость доп-работ, поправка на срочность. Поменять прайс — это отредактировать восемь чисел, не трогая разметку.
Вопросы по этому блоку
-
Допишите объект в массив EXTRAS: название, цену и признак — считается она за квадратный метр или разово. Чекбокс в интерфейсе появится сам, разметку править не нужно.
-
Да. Итоговая сумма и выбранные параметры пишутся в скрытое поле формы, поэтому в заявке видно, что именно человек насчитал.
-
Считает. Вся арифметика выполняется в браузере посетителя, запросов наружу блок не делает — это быстрее и не зависит от сторонних API.
-
Да. Код на этой странице копируется целиком, без регистрации и подписки. Указывать авторство не нужно, использовать можно в коммерческих проектах.
-
Нет. Все классы внутри имеют собственный префикс vbkrk, поэтому не пересекаются ни со стилями Tilda, ни с другими блоками. Скрипт привязан к своему элементу и запускается один раз, даже если блок вставлен дважды.
-
Раскладка перестраивается под узкие экраны, размеры заданы через clamp, поля ввода имеют шрифт 16 пикселей — iOS не будет зумить страницу при фокусе. Отдельной мобильной версии подключать не нужно.
Другие калькуляторы
Ещё блоки для ремонта и строительства
Собрать сайт целиком, а не по блокам
Дровосеки делают сайты на Tilda под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.