Блок «Мастера салона» для сайта салона красоты
Плитки мастеров с портретом, направлением и стажем. При наведении на портрет поднимается подпись о том, с чем мастер работает чаще всего, под именем стоит ближайшее свободное окно.
<section class="vbmsk">
<div class="vbmsk-wrap">
<div class="vbmsk-head">
<h2 class="vbmsk-h2">Мастера и ближайшие окна</h2>
<p class="vbmsk-lead">Направление, стаж и время, на которое ещё можно попасть на этой неделе. Наведите курсор на портрет или коснитесь его, чтобы прочитать, с чем мастер работает чаще всего.</p>
</div>
<div class="vbmsk-grid" id="vbmsk-grid"></div>
<p class="vbmsk-foot">Свободные окна показаны для примера. Актуальное расписание держит виджет записи: <a class="vbmsk-link" href="#zapis">выбрать время</a></p>
</div>
</section>
<style>
.vbmsk, .vbmsk *, .vbmsk *::before, .vbmsk *::after { box-sizing: border-box; }
.vbmsk {
--acc: #a35f66; --acc-dark: #8a4d54; --ink: #2f2429; --muted: #776a6e; --line: #ece0e1; --soft: #faf5f5;
--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;
}
.vbmsk-wrap { max-width: 1160px; margin: 0 auto; padding: 0 clamp(0px, 2vw, 40px); }
.vbmsk-head { max-width: 44em; margin-bottom: clamp(24px, 3vw, 40px); }
.vbmsk-h2 { font-family: var(--fh); font-size: clamp(26px, 3.4vw, 40px); line-height: 1.12; font-weight: 600; letter-spacing: -.02em; margin: 0 0 12px; }
.vbmsk-lead { font-size: 16px; line-height: 1.65; color: var(--muted); margin: 0; }
.vbmsk-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: clamp(14px, 1.6vw, 20px); }
.vbmsk-card { position: relative; background: var(--soft); border-radius: 18px; overflow: hidden; cursor: pointer;
opacity: 0; transform: translateY(10px); transition: opacity .45s ease, transform .45s cubic-bezier(.22,1,.36,1); }
.vbmsk-card.is-in { opacity: 1; transform: none; }
.vbmsk-card:focus { outline: 2px solid var(--acc); outline-offset: 3px; }
.vbmsk-pic { position: relative; overflow: hidden; }
.vbmsk-svg { display: block; width: 100%; height: auto; }
.vbmsk-hint { position: absolute; left: 0; right: 0; bottom: 0; padding: 16px 18px; background: rgba(47, 36, 41, .88);
transform: translateY(101%); transition: transform .32s cubic-bezier(.22,1,.36,1); }
.vbmsk-hint p { margin: 0; color: #fff; font-size: 13.5px; line-height: 1.5; }
.vbmsk-card:hover .vbmsk-hint, .vbmsk-card:focus .vbmsk-hint, .vbmsk-card.is-open .vbmsk-hint { transform: none; }
.vbmsk-body { padding: 16px 18px 18px; }
.vbmsk-name { font-family: var(--fh); font-size: 17px; font-weight: 600; line-height: 1.25; margin: 0 0 4px; }
.vbmsk-dir { font-size: 13px; color: var(--acc); font-weight: 500; margin: 0 0 12px; }
.vbmsk-dir i { font-style: normal; color: var(--muted); font-weight: 400; }
.vbmsk-slot { display: flex; align-items: center; gap: 8px; margin: 0; padding-top: 12px; border-top: 1px solid var(--line);
font-size: 13px; color: var(--muted); }
.vbmsk-slot b { color: var(--ink); font-weight: 600; }
.vbmsk-dot { flex: 0 0 7px; width: 7px; height: 7px; border-radius: 50%; background: var(--acc); }
.vbmsk-foot { margin: clamp(22px, 2.6vw, 32px) 0 0; font-size: 14.5px; line-height: 1.6; color: var(--muted); }
.vbmsk-link, .vbmsk-link:link, .vbmsk-link:visited { color: var(--acc) !important; text-decoration: underline; }
.vbmsk-link:hover { color: var(--acc-dark) !important; }
@media (prefers-reduced-motion: reduce) {
.vbmsk-card { opacity: 1 !important; transform: none !important; transition: none !important; }
.vbmsk-hint { transition: none !important; }
}
</style>
<script>
(function () {
/* ── МАСТЕРА: hair — форма причёски на заглушке: long, bun, wave, crop ── */
var STAFF = [
{ name: 'Анна Ковалёва', dir: 'Колорист', years: 11, c: '#efdcd8', hair: 'long', slot: 'вторник, 10:00',
spec: 'Сложное окрашивание на тёмную базу: растяжка, тонирование после смывки, возвращение своего цвета.' },
{ name: 'Ирина Сенина', dir: 'Мастер маникюра', years: 7, c: '#e6dee9', hair: 'bun', slot: 'сегодня, 18:30',
spec: 'Аппаратный маникюр, укрепление ногтей после наращивания, тонкая работа с кутикулой.' },
{ name: 'Мария Гурьева', dir: 'Бровист', years: 5, c: '#e3e2d5', hair: 'wave', slot: 'среда, 12:15',
spec: 'Форма бровей под черты лица, окрашивание краской и хной, ламинирование с укладкой.' },
{ name: 'Дарья Полякова', dir: 'Парикмахер-стилист', years: 9, c: '#e8dcd2', hair: 'long', slot: 'завтра, 15:00',
spec: 'Стрижки на тонкие волосы, укладки без плойки, работа с отросшей длиной и сечением.' },
{ name: 'Ольга Титова', dir: 'Косметолог', years: 12, c: '#dae3e2', hair: 'bun', slot: 'пятница, 11:00',
spec: 'Чистки, уходовые программы для чувствительной кожи, подбор домашнего ухода на сезон.' },
{ name: 'Егор Липатов', dir: 'Барбер', years: 6, c: '#dfe0e8', hair: 'crop', slot: 'суббота, 09:40',
spec: 'Стрижки машинкой и ножницами, оформление бороды опасной бритвой, камуфляж седины.' }
];
var roots = document.querySelectorAll('.vbmsk');
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('#vbmsk-grid');
var INK = 'rgba(58,42,47,.8)';
function portrait(c, hair) {
var s = '<svg class="vbmsk-svg" viewBox="0 0 200 210" aria-hidden="true" focusable="false">';
s += '<rect width="200" height="210" fill="' + c + '"/>';
if (hair === 'long') s += '<rect x="60" y="66" width="80" height="94" rx="30" fill="' + INK + '"/>';
s += '<circle cx="100" cy="92" r="32" fill="' + INK + '"/>';
if (hair === 'bun') s += '<circle cx="100" cy="50" r="13" fill="' + INK + '"/>';
if (hair === 'wave') s += '<path d="M67 88c0-21 15-35 33-35s33 14 33 35c-9-13-19-18-33-18s-24 5-33 18z" fill="' + INK + '"/>';
if (hair === 'crop') s += '<path d="M69 82c4-16 16-25 31-25s27 9 31 25z" fill="' + INK + '"/>';
s += '<path d="M44 210c0-31 25-49 56-49s56 18 56 49z" fill="' + INK + '"/>';
return s + '<\/svg>';
}
function yearWord(n) { var m = n % 100, k = n % 10; return m > 10 && m < 20 ? 'лет' : k === 1 ? 'год' : k > 1 && k < 5 ? 'года' : 'лет'; }
grid.innerHTML = STAFF.map(function (m) {
return '<article class="vbmsk-card" tabindex="0">' +
'<div class="vbmsk-pic">' + portrait(m.c, m.hair) +
'<div class="vbmsk-hint"><p>' + m.spec + '<\/p><\/div><\/div>' +
'<div class="vbmsk-body">' +
'<h3 class="vbmsk-name">' + m.name + '<\/h3>' +
'<p class="vbmsk-dir">' + m.dir + ' <i>· стаж ' + m.years + ' ' + yearWord(m.years) + '<\/i><\/p>' +
'<p class="vbmsk-slot"><span class="vbmsk-dot" aria-hidden="true"><\/span>Ближайшее окно: <b>' + m.slot + '<\/b><\/p>' +
'<\/div><\/article>';
}).join('');
var cards = Array.prototype.slice.call(grid.querySelectorAll('.vbmsk-card'));
cards.forEach(function (card) {
card.addEventListener('click', function () {
var open = card.classList.contains('is-open');
cards.forEach(function (o) { o.classList.remove('is-open'); });
if (!open) card.classList.add('is-open');
});
card.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ' || e.keyCode === 13 || e.keyCode === 32) { e.preventDefault(); card.click(); }
});
});
if (!('IntersectionObserver' in window)) { cards.forEach(function (c) { c.classList.add('is-in'); }); return; }
var io = new IntersectionObserver(function (es) {
es.forEach(function (e) {
if (!e.isIntersecting) return;
var i = cards.indexOf(e.target);
e.target.style.transitionDelay = Math.min(i, 5) * 60 + 'ms';
e.target.classList.add('is-in');
io.unobserve(e.target);
});
}, { rootMargin: '0px 0px -8% 0px' });
cards.forEach(function (c) { io.observe(c); });
setTimeout(function () { cards.forEach(function (c) { c.classList.add('is-in'); }); }, 2500);
}
})();
</script> Вставляется целиком в блок T123 «HTML-код». Внутри уже есть стили и скрипт, подключать ничего не нужно.
Как вставить блок в Tilda
- Скопируйте кодКнопка «Скопировать код» выше кладёт всё содержимое в буфер обмена.
- Добавьте блок T123В редакторе страницы: «Библиотека блоков» → «Другое» → T123 «HTML-код».
- Вставьте и сохранитеНажмите «Контент», вставьте код в поле, сохраните и обновите страницу.
- ОпубликуйтеВ превью скрипты Tilda работают не всегда — проверяйте на опубликованной странице.
Подробная инструкция с граблями — как вставить вайб-блок в Tilda.
Что менять под себя
| Где в коде | За что отвечает |
|---|---|
массив STAFF в начале скрипта | состав мастеров: имя, направление, стаж, окно записи |
поле spec у мастера | подпись, которая поднимается при наведении на портрет |
поле c и hair | цвет подложки и форма причёски на заглушке портрета |
--acc в стилях | цвет направления, точки у окна записи и ссылки под блоком |
Мастера салона красоты: зачем он нужен
В салон записываются к человеку, поэтому список мастеров работает как витрина. Посетителю важно понять три вещи: кто ведёт нужную услугу, сколько лет он в профессии и когда к нему можно попасть. Блок отвечает на все три в одной плитке и не заставляет открывать отдельную страницу. Строка со свободным окном снимает главное возражение: запись выглядит доступной уже сейчас.
Подробности спрятаны под наведение курсора, чтобы плитка оставалась короткой. На телефоне подпись открывается касанием, с клавиатуры плитка получает фокус и раскрывается тем же образом. Портреты нарисованы кодом: цветная подложка, силуэт и четыре варианта причёски, поэтому блок можно опубликовать до съёмки и подставить фотографии позже. Сетка построена на auto-fit, а появление плиток при прокрутке отключается в режиме уменьшенной анимации.
Вопросы по этому блоку
-
В скрипте замените вызов portrait на тег изображения с адресом из библиотеки Tilda и оставьте класс vbmsk-svg. Снимки лучше готовить в пропорции примерно 1:1,05, тогда они встанут на место заглушки без обрезки.
-
Да, касание плитки поднимает подпись и опускает её у соседней. То же самое делает клавиша пробела или ввода, когда плитка выбрана с клавиатуры.
-
Это обычный текст в поле slot, он не связан с расписанием. Поставьте туда живые дни или уберите строку целиком, если расписание меняется каждый час, а ссылку внизу направьте на виджет записи.
-
Да. Код на этой странице копируется целиком, без регистрации и подписки. Указывать авторство не нужно, использовать можно в коммерческих проектах.
-
Нет. Все классы внутри имеют собственный префикс vbmsk, поэтому не пересекаются ни со стилями Tilda, ни с другими блоками. Скрипт привязан к своему элементу и запускается один раз, даже если блок вставлен дважды.
-
Раскладка перестраивается под узкие экраны, размеры заданы через clamp, поля ввода имеют шрифт 16 пикселей — iOS не будет зумить страницу при фокусе. Отдельной мобильной версии подключать не нужно.
Другие блоки команды
Ещё блоки для салонов красоты
Собрать сайт целиком, а не по блокам
Дровосеки делают сайты на Tilda под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.