Всё, из чего собран магазин, на одной странице. Новая страница берётся отсюда, а не рисуется заново — так кнопки и окна остаются одинаковыми. Стили те же самые, что на сайте: если элемент здесь сломался, он сломан и там.
Высота одна на все, скругление и минимальная ширина тоже — числа берутся из вида набора, а не пишутся здесь. Порядок в ряду: слева второстепенные, справа главная.
.btn · .btn-primary · .btn-ghost · .btn-sm · .btn.del
.btn-group
.btn со значком, во всю ширину
Ряд кнопок в окне и в полосе сохранения ставится так: «По умолчанию · Отменить · Сохранить».
Кегль на телефоне не мельче 16 точек: иначе iOS увеличивает страницу при касании.
.field · select.field · textarea.field
.igroup · .fix · .gl
.fld.bad · .field.bad
Сам тумблер мелкий намеренно, но зона нажатия у него добита до нормы в 24 точки — иначе пальцем не попасть.
.sw.sw.on.q — подсказкаСлова с заглавной буквы, цвет — по смыслу: зелёный работает, жёлтый требует внимания, красный не работает.
.pill.on.pill.warn.pill.off.pillСтрока настройки — один образец на всю панель: слева название и пояснение, справа управление.
Короткое пояснение, о чём этот блок
.kpi-row · .kpi
1,2 литра, автоотключение
1,7 литра, подсветка
.card · .ratio
.kpi-row · .kpi
1,2 литра, автоотключение
1,7 литра, подсветка
.card · .ratio
На телефоне строки складываются в карточки: прокрутка вбок прячет правый край с кнопкой, и владелец её не находит.
Когда вариантов больше двух, несколько тумблеров подряд читаются как независимые, хотя выбрать можно только один. Для такого случая — сегменты.
.seg > button.on
.seg.sm — над списком
.toggle / .toggle.on — залипающая кнопка
Для того, что сравнивают по столбцам: оплаты, промокоды, журнал. На телефоне строки
складываются в карточки — подпись столбца берётся из data-подпись.
| Дата | Клиент | Тариф | Сумма | Способ | |
|---|---|---|---|---|---|
| 19.08.2026 | Аня | Месяц | 149 ₽ | Рубли | |
| 17.08.2026 | Дмитрий Селезнёв | Год | 1 299 ₽ | Звёзды |
Полоса отвечает на «сколько уже», поэтому число рядом обязательно. Заглушки показывают будущую форму списка, пока данные едут: пустой экран читается как «ничего нет», и человек уходит раньше времени.
.prog + .bar
.bar.warn — подходит к пределу
.skel-row — список на время загрузки
Боковое меню — когда разделов много и они равноправны. Горизонтальное — когда их пять-шесть, а место по бокам дорого.
Панель, где разделов больше, чем помещается в один список: сверху переключатель между группами, под ним — пункты выбранной группы. Так меню не растёт в бесконечный столбец, а человек не ищет нужное среди двадцати строк.
.sidebar · .nav-head · .seg.wide · .nav · .nav-foot
Строка с почтой стоит НАД переключателем: сперва человек убеждается, что он в нужной учётной записи, и только потом переключает раздел. Наоборот — и переключение уходит не туда, куда он думал.
Готовый кусок для витрины и лендинга. Собран из тех же кнопок и меню. Подвал живёт отдельным блоком — «Подвал сайта» ниже по списку.
.site-head
Одна карточка на все случаи — вход, регистрация, восстановление пароля. Отличаются набором полей, а не оформлением. Эта же карточка стоит на входе покупателя, на регистрации и на входе в управление.
Заказы, адреса и избранное — в одном месте
.auth-card — вход
Заведи учётную запись — займёт минуту
.auth-card — регистрация
Вторая карточка входа в наборе была лишней: .form-card осталась от панели и не работала ни на одной странице. Осталась одна — та, что держит вход покупателя, регистрацию и вход в управление.
Открывается с клавиатуры и кнопкой в шапке. Ищет сразу везде: клиентов, разделы, действия — чтобы не помнить, где что лежит. Ниже окно показано открытым.
.find · .find-input · .find-list · .find-item
Выбранный пункт подсвечивается заливкой, а не рамкой: рамка прыгает при движении стрелками и рябит.
Плашка говорит о состоянии дел и остаётся, пока причина не устранена. Про результат действия сообщает всплывающее уведомление внизу — оно исчезает само.
Сертификат выпускается, обычно это минута.
Клиенты видят только звёзды.
Первое ждёт три часа.
before-1.55.0 · 400 КБ
.spin · .spin.lg
Меню действий — что можно сделать. Карточка — что это такое. Подсказка — что значит значок. Путать их нельзя, иначе человек ищет действие там, где показаны данные.
.menu — действия
.pop — данные
.tip-host + .tip
Раскрывашка прячет то, что нужно не всем: редкие настройки, подробности. Прятать за ней главное нельзя — не найдут. Шаги показывают, сколько всего и где человек сейчас.
Аватарки, значки, клавиши, строки списка. Именно из-за них интерфейс выглядит собранным или сшитым наспех.
.ava · .ava-row
.badge · .kbd
Окно — короткое действие. Боковая шторка — работа рядом с содержимым: страница остаётся видна. Нижняя — то же на телефоне, до неё дотягивается большой палец.
Вместе с ним пропадут его конфиги и история оплат. Отменить будет нельзя.
Обычное поле закрывает почти всё. Здесь случаи, где его не хватает.
.igroup — поле с приставкой
.igroup — с единицей и кнопкой
.otp — код подтверждения
.count — счётчик
Выбор даты окончания подписки и периода отчёта. Клетка ростом с мелкую кнопку — в календарь тычут пальцем чаще, чем куда-либо ещё.
Наши сообщения справа, клиента слева — как в любом мессенджере, спорить с привычкой незачем. Время и признак прочтения внутри пузыря, иначе они рвут ленту.
Для того, что пишет человек: правовые документы, описание тарифа, ответ поддержки. Строка не длиннее семидесяти двух знаков — иначе глаз теряет начало следующей.
Подписка даёт доступ ко всем серверам сервиса. Устройств можно подключить столько, сколько указано в тарифе — каждое получает свой конфиг.
Если конфиг перестал работать, перевыпусти его в кабинете — старый сразу перестаёт действовать.
Инструменты над таблицей, поле с календарём, карточка по наведению, выделение в тексте и опросник.
.tbl-tools — инструменты над таблицей
.datefield — поле с календарём
.hover-card — данные по наведению
mark · .marker.plain — выделение в тексте
Отвечают на три вопроса сразу: что это, сколько и куда движется. Прежние плитки показывали только число — а много это или мало, понять было нельзя.
Цифры моноширинные: сводка обновляется каждую минуту, и от прыгающей ширины цифр плитки дёргались бы.
Заголовок, пояснение и управление в одной строке. На узком экране действие переезжает под заголовок: имя карточки важнее кнопки, обрезать его нельзя.
Отдано клиентам и принято, гигабайты в сутки
.ch — шапка · .period — переключатель срока
Вкладка переключает набор одних и тех же данных. Если за ней прячется другое содержимое — это раздел, и ему место в меню.
| Дата | Клиент | Тариф | Сумма | |
|---|---|---|---|---|
| 19.08.2026 | Аня | Месяц | 149 ₽ | |
| 17.08.2026 | Дмитрий Селезнёв | Год | 1 299 ₽ |
.tabs-row · .tabs · .tabs > button.on
Номер вводят чаще любого другого поля — и ошибаются в нём чаще всего: каждый пишет по-своему. Приставка «+7» стоит внутри поля и не стирается, цифры сами встают как «900 000-00-00».
.tel + data-телефон (поведение из kit.js)
Форме уходит номер целиком, «+79001234567»: скрытое поле рядом подставляется при отправке. Видимое остаётся читаемым для человека.
Половина вопросов задаётся до покупки, и звонить ради них не пойдут. Чат сделан один раз и встраивается: разметка ниже, оформление и поведение приезжают с набором. От сайта нужны только две ручки на сервере.
<div class="чат" data-чат
data-опрос="/api/chat/poll"
data-отправка="/api/chat/send">
<button class="чат-вызов" data-чат-кнопка aria-label="Чат">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5.5h16v10H8.5L4 19z"/><path d="M8 9.5h8"/><path d="M8 12.5h5"/></svg>
<span class="чат-счёт" data-чат-счётчик hidden></span>
</button>
<div class="чат-окно" hidden data-чат-окно role="dialog">
<div class="чат-шапка">
<b>Чат с магазином</b>
<button class="чат-закрыть" data-чат-закрыть>✕</button>
</div>
<div class="чат-лента" data-чат-лента></div>
<form class="чат-форма" data-чат-форма>
<textarea class="field" data-чат-поле data-рост placeholder="Напишите сообщение"></textarea>
<button class="btn btn-primary">Отправить</button>
</form>
</div>
</div>
<script src="/static/chat.js" defer></script>
.чат · .чат-вызов · .чат-окно · chat.js
От сервера нужны две ручки. Опрос отвечает
{"сообщения":[{"номер":7,"сторона":"shop","текст":"…"}]},
отправка принимает {"текст":"…","страница":"/cart"}.
Адреса задаются в разметке, поэтому у каждого сайта они свои.
На телефоне окно открывается во весь экран — как в мессенджерах.
Куски страницы, из которых собирается лендинг и главная магазина: первый экран, блок возможностей, вопросы, контакты, баннер.
.banner · .hero — первый экран
.feat.cards — блок возможностей
.faq — вопросы и ответы
Карточка отвечает на четыре вопроса по порядку: что это, как называется, сколько стоит, можно ли купить сейчас. Остальное — на странице товара.
.prod-grid · .prod — карточка товара
На телефоне сетка встаёт в две колонки, а не в одну: одна колонка превращает каталог в бесконечную ленту, и до третьего товара не долистывают.
Четыре вещи, ради которых открывают шапку: найти товар, попасть в каталог, увидеть корзину, войти к себе. Верхняя строка — служебная, нижняя липнет к верху при листании.
.promo-bar · .shop-head
.promo-bar.тёмная · .promo-bar.тихая
.shop-head[data-вид="витрина"]
Полоса акции не липнет к верху нарочно: на телефоне она съедает высоту экрана, а сообщение в ней читают один раз.
Одно дерево разделов в трёх видах: столбцом на странице каталога, раскрытием во всю ширину из шапки и путём над заголовком.
.crumbs — путь до страницы
.cat-side — столбец · .mega — раскрытие из шапки
Раскрытие держится на скрытом флажке, а не на наведении: открытое по наведению меню закрывается, стоит увести мышь на пиксель.
Справочная страницы: телефон с адресом и то, чего не нашли в меню — доставка, возврат, договор. Колонки неравные нарочно, первая про магазин.
.site-foot — подвал сайта
На телефоне колонки ссылок сворачиваются, а первая остаётся открытой: телефон прятать нельзя, за ним и приходят.
Две секции про одно: как до вас достучаться. Полей в форме ровно три — каждое лишнее поле в обратной связи стоит десятой части отправивших, а уточнить можно и по телефону.
Ответим в рабочее время, обычно в течение часа. Если вопрос про заказ — держите под рукой его номер, так быстрее.
.связь-блок
.локация
Место под карту задано заранее: без этого страница прыгает, когда врезка догрузится, и человек промахивается мимо кнопки.
Три вещи, без которых не обходится ни один разбор: карточка заказа, страница клиента, свойства товара. До сих пор каждый экран рисовал их по-своему — отсюда и разнобой в управлении.
.свойства
.свойства.столбиком
.история · .шаг.готово · .шаг.сейчас
Таблица со всеми заказами за выбранный период — для бухгалтерии и для сверки с банком.
Уйдут товары, заказы, покупатели и снимки. Восстановить можно только из копии, если она есть.
.действие · .действие.опасно
Опасное действие помечено рамкой и красным заголовком, но фон обычный: красная заливка кричит на человека каждый раз, когда он просто листает настройки.
Мелочи, из которых собрана половина экранов: товар в списке, человек в переписке, файл во вложениях, ряды карточек и линия с подписью посреди содержимого.
Чёрная, 1,2 литра, автоотключение
1,7 литра, подсветка, защита от включения без воды. Забирают чаще всего вместе с кофеваркой.
.медиа · .медиа.крупно
248 товаров
180 товаров
96 товаров
54 товара
31 товар
.разделы-сетка · .разделы-сетка.разно
.разделитель-текст
Число колонок в сетке не задаётся: оно считается от места, поэтому одна и та же сетка годится и в широкой странице, и в узкой колонке рядом с фильтрами.
Три секции, которые ставят на главную чаще прочих. Плеер не грузим сразу: чужая врезка тянет мегабайт скриптов и видит каждого посетителя. Показываем обложку, а плеер подставляется по нажатию.
.видео
3 990 ₽
2 190 ₽
1 450 ₽
2 800 ₽
990 ₽
240 ₽
.лента-обёртка · .лента-карточек
Скидка на все кофеварки и кофемолки. Промокод не нужен, цена уже в карточке.
до 31 августа Смотреть товары.спец · .предложение.главное
Срок показан приглушённо: крикливый таймер читается как обман, а именно срок и заставляет решать сейчас.
Снимки товара, накладная, картинка в статью. Обычное поле выбора файла выглядит чужеродно и по-разному в каждом браузере, поэтому его прячут и рисуют своё. Перетаскивание — не единственный способ: по области можно и просто нажать.
.кладь
.кладь.несут
.кладь-список · .файл
Полоса загрузки идёт прямо в строке файла: отдельная полоса под списком не показывает, какой именно файл ещё едет.
Про доставку спрашивают до того, как положат товар в корзину. Пока ответа нет на странице, его спрашивают в чате — или уходят. Два вида: карточки для страницы условий и сжатая полоса под кнопкой на странице товара.
Привезём в удобное время, позвоним за час. Оплата картой курьеру.
Кроме области — уточняйте зону Завтра до 14:00БесплатноБольше двухсот пунктов: заберёте, когда удобно, хранение семь дней.
Примерка на месте Послезавтра190 ₽Москва, улица Складская, 5. Ежедневно с 9:00 до 20:00.
Заказ ждёт три дня Сегодня через два часаБесплатноКартой на сайте, при получении или по счёту для организаций.
MIRVISAMCSBPНаличные.доставка · .способ
.доставка.строкой
Срок и цена стоят в одной строке и в самом низу карточки: способы сравнивают, ведя взглядом по одной линии. «Бесплатно» показано цветом «хорошо» — это довод, а не цена, и среди рублей соседних способов оно теряется.
Фильтры работают, только когда видно и что можно выбрать, и что уже выбрано. Поэтому выбранное вынесено отдельной строкой над товарами, а число товаров стоит у каждого значения.
.sort-bar · .view-switch
.picked — выбранные фильтры строкой
.filters — столбец фильтров
Число товаров у значения не украшение: без него ставят галочку и получают пустой каталог, а это уже похоже на поломку магазина.
Всё, что отвечает на «точно ли то самое», стоит на первом экране: фото, название, цена, наличие, кнопка. Галерея и блок покупки липкие — человек читает описание, не теряя товар из виду.
Готовит до десяти чашек за раз, держит температуру сорок минут и отключается сама. Съёмный фильтр моется в посудомоечной машине.
| Мощность | 1 100 Вт |
| Объём | 1,2 литра |
| Тип фильтра | Многоразовый, нейлон |
| Гарантия | 24 месяца |
.prod-page · .gallery · .vars · .buy-box
Варианты — плашками, а не выпадающим списком: из списка не видно, чего нет в наличии, а перебирать по одному — работа.
Последняя проверка перед деньгами: тот ли товар, сколько штук, сколько за них. Итог держится липким справа и не уезжает при листании.
.cart · .cart-row · .cart-sum
Удалённая строка остаётся на месте с возвратом: промах пальцем в корзине стоит дороже всего — человек не помнит, что смахнул, и уходит собирать заново.
Место, где теряют больше всего покупателей. Шаги пронумерованы, сумма не исчезает, способы доставки и оплаты — крупными плашками.
.checkout · .pick · .order-sum
Согласие стоит под кнопкой, а не над ней: сначала действие, потом мелкий шрифт. Прятать его нельзя, требовать галочку — можно.
Отзывам верят, когда видно распределение оценок и живого человека: имя, дату, что именно купил. Магазин со ста пятёрками выглядит хуже магазина с тремя двойками и ответом.
Взяла вместо старой рожковой — варит быстрее и мыть проще. Держит температуру действительно долго, утром кофе ещё горячий.
Пришла с царапиной на корпусе. Работает нормально, но осадок остался.
Сергей, извините. Заменили бы сразу — напишите нам, оформим замену без возврата товара, курьер привезёт новую и заберёт эту.
.reviews · .review · .rating
Звёзды сделаны одним приёмом: серый ряд снизу, жёлтый сверху обрезан по ширине оценки. Половинки получаются сами, отдельной картинки не нужно.
Списки в колонках совпадают построчно — иначе сравнение превращается в чтение трёх разных текстов. Средний приподнят и подписан честно: «Берут чаще всего», а не «Лучший выбор».
Один тариф, два срока. Чем длиннее срок, тем дешевле месяц.
.price-block · .price-grid · .plan
Годовая цена показана за месяц с пометкой о списании разом: крупная сумма за год отпугивает, спрятанная — злит при оплате.
Главная отвечает на вопрос «что тут есть». Плитки отвечают быстрее списка: картинка узнаётся раньше, чем читается слово. Первая крупнее — раздел, который продаёт лучше всех.
.cats · .плитка · .плитка.крупно
На телефоне остаются две колонки: одна растягивает десять разделов на три экрана, и до нижних не долистывают.
Человек дочитал и согласен — ему должно быть куда нажать. Кнопка ровно одна: две равные превращают призыв в выбор, и на нём останавливаются.
Три дня бесплатно, карта не нужна. Не понравится — просто не продлевайте.
.cta.цветной
Отвечаем в течение часа, без роботов и очередей.
.cta.в-рамке
Одно письмо в неделю, без рекламы чужих товаров. Отписаться можно в один клик.
.subscribe
Одно письмо в неделю
.subscribe.полоса
Мелкая строка под кнопкой снимает последнее возражение: «без карты», «отмена в один клик». Работает лучше ещё одного абзаца выше.
Три способа сказать «нам можно верить». Работают только конкретные цифры: «10 480 заказов за 2025 год» вместо «более 10 000 клиентов».
.figures
.logos
.team
Роль пишем понятную покупателю, а не должность из штатного расписания: «Отвечает на вопросы о доставке» вместо «Менеджер отдела логистики».
Статьи держат людей на сайте и приводят из поиска. Колонка текста узкая нарочно: строка во всю ширину монитора не читается — глаз теряет начало следующей.
Разбираем по трём вопросам: сколько чашек в день, сколько времени готовы тратить и сколько места на кухне.
Дмитрий 7 минут Обложка УходНакипь убивает нагреватель быстрее всего остального.
Анна4 минуты.post-grid · .post · .post.главная
Выбор кофеварки сводится к трём вопросам, и цена среди них — последний. Сначала ответьте себе, сколько чашек в день вы пьёте.
До двух чашек — подойдёт любая. От четырёх — берите капельную с объёмом от литра, иначе будете варить дважды за утро.
Самая частая ошибка — купить рожковую «чтобы как в кофейне» и через месяц вернуться к растворимому: возни много, а разница заметна не всем.
.article · .toc · .author
Оглавление липкое: в длинной статье оно заменяет полосу прокрутки — видно, где ты и сколько осталось.
На них попадают в худшую минуту: что-то не нашлось, сломалось или человек только что отдал деньги. Устроены одинаково — знак, короткий заголовок, строка объяснения, одно действие.
Отправили подтверждение на почту. Курьер позвонит завтра с 10:00 до 14:00.
.state-page.успех
Такие мы пока не возим, но есть похожее.
.state-page.внутри — пусто
Что-то сломалось у нас, а не у вас. Уже чиним — попробуйте обновить через минуту.
.state-page.беда
На странице ошибки не пишем «Ошибка 404» заголовком: это код для нас. Номер оставляем мелко внизу — по нему человек опишет проблему в поддержке.
Кабинет открывают ради одного вопроса: где мой заказ. Поэтому заказы первым пунктом, а состояние показано словами и полосой шагов, а не цветной точкой.
.lk · .lk-menu · .order
У отменённого заказа шаги серые целиком: зелёная половина полосы у отменённого заказа выглядит издевательством.
Все одинаковые: значок, короткая фраза и подсказка, что сделать. Не смешивать «Пусто», «Нет данных» и «Ничего нет».
Берутся из общего набора токенов, а не пишутся числом. Акцент задаётся владельцем в настройках и меняется вместе с темой.
Оформление лежит по разделам в web/styles/, одна тема —
один файл. В браузер уходит один собранный файл: командой
python tools/build_styles.py. Список собран из того, что
лежит на диске прямо сейчас, — руками его не правят.
Раздел «Панель» в другие проекты не едет: там внутренности панели
управления. Всё остальное переносится командой
python tools/export_kit.py.