DESIGN.md
Портфолио-сайт продуктового дизайнера. Лонгриды кейсов, резюме, блог. Визуал — минимализм с акцентом на типографику и контент.
Продукт
Одностраничный сайт-портфолио с внутренними страницами (кейсы, резюме, блог). Основной контент — лонгриды с описанием проектов. Навигация через главную страницу с секциями: навыки, портфолио, контакты.
Характер: Сдержанный, профессиональный. Без визуального шума. Контент — главный элемент интерфейса.
Цвета
Токены темы
| Токен |
Назначение |
--theme-h |
Оттенок акцента (0–360°) |
--theme-s |
Насыщенность акцента |
--theme-l |
Светлота акцента |
--accent |
Основной акцентный цвет |
--accent-text |
Цвет текста на акцентном фоне |
--accent-soft |
Мягкий акцент для фона |
--bg |
Фон страницы |
--bg-elevated |
Поверхность второго уровня |
--surface |
Фон карточек и секций |
--text |
Основной текст |
--text-muted |
Приглушённый текст |
--line |
Рамки и разделители |
Правила
- Акцент меняется через
--theme-h/s/l на <html>. Все производные пересчитываются автоматически.
- Светлая/тёмная тема —
data-theme="light|dark" на <html>.
- Нейтральные фоны (
--bg, --surface) слегка подмешивают оттенок акцента через --neutral-accent-tint.
- Не используйте хардкод hex-значений. Всегда обращайтесь к токенам.
Типографика
Семейства
data-font |
Стек |
Назначение |
merriweather |
Merriweather + Alice |
По умолчанию. Alice — проза, Merriweather — заголовки |
geologica |
Geologica + PT Sans |
Гротеск + нейтральная проза |
mono |
Source Code Pro + PT Mono |
Моноширинный |
Шкала
| Класс |
Размер |
Вес |
Назначение |
.hero__eyebrow |
0.78rem |
700 |
Подзаголовок секции, ввод кейса. Uppercase, letter-spacing 0.14em |
.hero__title |
clamp(3.1rem, 7.2vw, 4.85rem) |
700 |
H1 главной страницы |
.case-page__h1 |
clamp(2rem, 3.9vw, 2.9rem) |
700 |
H1 кейса / внутренней страницы |
.case-page__sub |
clamp(1.5rem, 2vw, 1.65rem) |
500 |
Подзаголовок под H1 |
.section__title |
clamp(0.95rem, 1.35vw, 1.1rem) |
600 |
Заголовки секций («Навыки», «Портфолио») |
.section__prose |
наследует |
— |
Основной текст абзацев |
h2 в .case-article |
clamp(1.5rem, 2vw, 1.65rem) |
500 |
Разделы лонгрида |
h3 в .case-article |
наследует |
— |
Подразделы внутри H2 |
Правила
- Заголовки используют
clamp() — размер масштабируется от вьюпорта.
- Не задавайте
font-size в пикселях. Используйте rem или clamp().
line-height для прозы: 1.55 (базовый), для заголовков: 1.2.
max-width текстовой колонки: 42rem (.section__prose).
Отступы и сетка
Токены
| Токен |
Значение |
Назначение |
--space |
clamp(1rem, 4vw, 2.75rem) |
Горизонтальные поля + safe-area |
--max |
none |
Ширина контента = вьюпорт минус padding |
--radius-sm |
Зависит от data-radius |
Малые скругления |
--radius-md |
Зависит от data-radius |
Средние скругления |
--radius-card |
Зависит от data-radius |
Карточки |
Секции
| Класс |
Назначение |
.section |
Вертикальные отступы через clamp() |
.section--tight |
Компактные отступы (кейсы, внутренние страницы) |
.section--surface |
Прозрачный фон (для mesh на главной) |
.section__inner |
Центрированная обёртка с max-width: var(--max) |
.case-article |
Контентная колонка лонгрида: max-width: 48rem |
Брейкпоинты
| Ширина |
Что меняется |
860px |
Hero → 2 колонки (1.15fr 0.85fr) |
760px / 1180px |
Карусель портфолио: 1 → 2 → 3 карточки |
720px |
Сетка навыков → 2 колонки |
1024px |
Навыки: 6-колоночная мозаика |
560px / 1024px |
Контакты → 2 → 4 колонки |
640px |
Wide-блоки схлопываются в ширину колонки |
Правила
- Отдельной 12-колоночной сетки нет. Используйте CSS Grid внутри секций.
- Горизонтальные отступы —
--space + safe-area-inset.
- Wide-блоки (
.case-media--wide, .case-callout) шире колонки: min(100vw - 2*padding, content + 8rem).
Компоненты
Кнопки
| Класс |
Назначение |
.btn |
Базовый класс кнопки |
.btn--primary |
Основная кнопка (акцентный фон, стекло) |
.btn--secondary |
Вторичная кнопка (нейтральное стекло) |
.btn--ghost |
Текстовая кнопка без фона |
.btn--flat |
Плоский вариант (без «объёма») |
.btn--raised |
Приподнятый вариант (с тенью) |
.btn__icon |
Иконка внутри кнопки |
FAB-кнопки
| Класс |
Назначение |
.fab |
Базовый класс плавающей кнопки (круглая, position: fixed) |
.fab--primary |
Акцентная FAB (градиент, стекло, --on-accent для текста/иконки) |
.fab--secondary |
Вторичная FAB (нейтральная, для настроек) |
.fab--label |
Модификатор: снимает фиксированную ширину, добавляет текст рядом с иконкой |
.fab-primary__ico |
Иконка внутри primary FAB (маска через mask-image) |
.fab__label |
Текстовая подпись внутри FAB |
Правило: --on-accent вычисляется в синхронном theme-init-script (в <head>) по luminance акцента. Не задавайте color вручную — наследуется от .fab--primary.
Теги
| Класс |
Назначение |
.hero__tags |
Контейнер тегов в Hero |
.hero__tag |
Тег (пилл с рамкой). Используйте для ключевых слов |
.portfolio-card__tag |
Тег внутри карточки портфолио |
.mp-card__tags |
Контейнер тегов в mp-card |
.mp-card__tag |
Тег внутри mp-card |
Фильтр-чипы
Переключаемая группа тегов над списком карточек. Нажатый чип оставляет только элементы с
совпадающим тегом, остальные скрываются.
| Класс / атрибут |
Назначение |
.filter-chips |
Контейнер чипов (<ul>). Атрибут data-filter-chips включает поведение |
.filter-chip |
Кнопка-чип. Атрибут data-filter-value = тег, который она включает |
.filter-chip__count |
Счётчик совпадений. Проставляется скриптом автоматически |
data-filter-scope |
Селектор контейнера с фильтруемыми элементами. По умолчанию document |
data-filter-item |
Помечает фильтруемый элемент |
data-filter-tag |
Теги элемента через пробел. Несколько тегов работают как OR |
Правила:
- Состояние держится в
aria-pressed="true|false", а не в классе. Оформление выбранного
чипа — [aria-pressed="true"], поэтому оно не зависит от :focus и не залипает после клика.
- Значение
all (или пустое) показывает все элементы. Такой чип обычно первый.
- Скрытие через атрибут
hidden + [data-filter-item][hidden] { display: none } — сетка
не оставляет дыр. Плавное затухание потребовало бы анимации высоты, а для фильтра
мгновенный отклик важнее.
- JS:
initFilterChips() в public/js/modules/ui/filter-chips.js, подключён в main.js.
Счётчики и стартовое состояние берутся из разметки, модуль сам их заполняет.
- Помечайте элементы
hidden, а не удаляйте — иначе фильтр ломает раскладку при возврате.
Карточки
| Класс |
Назначение |
.portfolio-card |
Карточка проекта в портфолио |
.portfolio-card__body |
Текстовая часть |
.portfolio-card__cover |
Обложка |
.skill-task-card |
Карточка навыка (задача + решения) |
.contact-card |
Контактная карточка (ссылка или действие) |
Блоки лонгрида
| Класс |
Назначение |
.hero__eyebrow |
Подзаголовок перед H1 |
.case-page__h1 |
Заголовок страницы |
.case-page__sub |
Подзаголовок |
.section__prose |
Абзац текста |
.section__title |
Заголовок секции |
.case-callout |
Акцентный блок (важная мысль) |
.case-media |
Обёртка для изображения/видео |
.case-media--natural |
Изображение в натуральном масштабе |
.case-media--content |
По ширине текстовой колонки |
.case-media--wide |
Шире колонки статьи |
.case-media-gallery--wide |
Шире колонки статьи (галерея) |
.case-media-slider |
Слайдер: одна картинка, стрелки и точки-пагинация |
Поведение
Изображения
- Формат: WebP для всех изображений.
- Видео: WebM (MP4 как fallback).
- Lazy loading:
loading="lazy", decoding="async".
- Просмотр по клику:
data-image-viewer на <img>.
- Заглушка при загрузке:
.is-img-loading / .has-img-loading.
Секции
- Порядок на странице кейса:
header-case → fab-stack → main.case-article → projects-section → contact-section → footer.
- Порядок на внутренних страницах:
header-minimal → fab-stack-home-contact → main.section → footer.
Навигация
- Главная: горизонтальная навигация по секциям.
- Внутренние страницы: ссылка «на главную» в шапке.
- Плавающие кнопки (FAB): тема, контакты.
Do's and Don'ts
Do's
- Используйте токены цвета (
--accent, --text, --surface), не хардкодьте.
- Используйте
clamp() для типографики — не фиксированные px/rem.
- Используйте
.section__prose для основного текста — он задаёт max-width и color.
- Используйте
.hero__eyebrow для подзаголовков перед заголовками.
- Используйте WebP для изображений, WebM для видео.
- Для лонгридов внутри
.case-article — заголовки h2/h3 стилизуются автоматически.
Don'ts
- Не создавайте новые классы для типографики, если есть готовые в таблице шкалы.
- Не используйте
font-size в пикселях.
- Не смешивайте стили из разных
data-font на одной странице.
- Не используйте
.hero__tag для навыков в резюме — используйте .skill-card или простой список.
- Не создавайте wide-блоки без необходимости — они выходят за колонку и ломают ритм.
- Не используйте декоративные градиенты на функциональных поверхностях.
Страницы
| Страница |
Шаблон |
Ключевые компоненты |
| Главная |
src/pages/index.html |
Hero, Skills, Projects, Contact |
| Кейс |
src/pages/cases/*.html |
.case-article, .hero__eyebrow, .case-page__h1, .case-media |
| Резюме |
src/pages/resume*.html |
.doc, .profile-header, .meta-grid, .timeline, .skill-grid |
| Design System |
src/pages/cases/design-system.html |
Живой каталог компонентов и токенов |
| Demo elements |
src/pages/cases/template-elements-demo.html |
Элементы лонгрида: медиа, галереи, видео, callout |
| Mini projects |
src/pages/cases/mini-projects-showcase.html |
Карточки активности (mp-card) |
Файлы
| Файл |
Назначение |
public/css/main.css |
Единый CSS: токены + все компоненты |
src/pages/cases/design-system.html |
Живой каталог токенов, типографики, кнопок, карточек |
src/pages/cases/template-elements-demo.html |
Элементы лонгрида: медиа, галереи, видео, callout |
src/pages/cases/mini-projects-showcase.html |
Карточки активности (mp-card) |
docs/case-page-blocks.md |
Инструкция по блокам лонгридов |
DESIGN.md |
Этот файл — описание для AI-агентов |