Блок «Мастера салона» для сайта салона красоты
Плитки мастеров с портретом, направлением и стажем. При наведении на портрет поднимается подпись о том, с чем мастер работает чаще всего, под именем стоит ближайшее свободное окно.
<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 под ключ: структура, тексты, дизайн, вёрстка и вайб-блоки под задачи бизнеса.