Design System
Все визуальные решения, токены и компоненты в одном месте. Используется дизайнерами, разработчиками и всеми, кто работает с интерфейсами oqprint.ru.
Цвета
Палитра строится на двух шкалах: Primary (синий) и Grey (нейтральный). Все цвета доступны через CSS-переменные.
Primary
Grey
Семантические токены
| Токен | Light | Dark | Использование |
|---|---|---|---|
--bg |
#ffffff | #171819 | Фон страницы |
--surface |
#edeeee | #343637 | Фон карточек, блоков |
--border |
#c3c7c9 | #555859 | Границы, разделители |
--text |
#171819 | #edeeee | Основной текст |
--muted |
#555859 | #9ba0a3 | Второстепенный текст, подписи |
--accent |
#0081bd | #00a8f4 | Ссылки, кнопки, фокус |
Статусные цвета
Типографика
Шрифт — Raleway (Google Fonts). Базовый размер 16px, line-height 1.6. Все заголовки — weight 700.
--accent: #0081bdОтступы
Шкала на базе 4px. Основные значения кратны 4 или 8.
Границы
Система без скруглений — border-radius не используется. Все границы — 1px solid.
| Свойство | Значение | Использование |
|---|---|---|
border-width |
1px | Единственная используемая толщина |
border-style |
solid | Всегда solid |
border-color |
var(--border) |
Стандартный цвет границы |
border-radius |
0 | Не используется — острые углы |
Анимация
Минимальные, функциональные переходы. Без декоративных анимаций.
| Токен | Значение | Использование |
|---|---|---|
--duration-fast |
100ms | Hover опций в списке (dropdown, date-card) |
--duration-base |
150ms | Hover кнопок, границ, триггеров — всё по умолчанию |
--duration-slow |
250ms | Открытие/закрытие панелей, смена темы |
--easing-default |
ease | Стандартная функция — везде |
--easing-in-out |
ease-in-out | Для элементов с чётким началом и концом (chevron) |
| Допустимые свойства | color, background, border-color, opacity, transform | Только функциональные — без декоративных эффектов |
Правила
| ✓ | Анимируй только изменения состояния (hover, focus, open, selected) |
| ✓ | Используй transition на элементе, а не на псевдоклассе |
| ✗ | Не используй анимации при первой загрузке страницы |
| ✗ | Не анимируй size, width, height — дорого для браузера |
| ✗ | Не используй bounce, elastic или длительность > 300ms для UI |
/* CSS-переменные из components.css */
:root {
--duration-fast: 100ms;
--duration-base: 150ms;
--duration-slow: 250ms;
--easing-default: ease;
}
/* Применение */
.btn {
transition: background var(--duration-base) var(--easing-default),
border-color var(--duration-base) var(--easing-default);
}
.cd__option {
transition: background var(--duration-fast) var(--easing-default);
}
Подключение
Все компоненты находятся в одном файле. Подключи его после base.css.
<!-- 1. Токены и базовые стили --> <link rel="stylesheet" href="/shared/base.css"> <!-- 2. Компоненты --> <link rel="stylesheet" href="/shared/components.css"> <!-- 3. Шрифты --> <link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
Кнопки
Три варианта (Primary, Secondary, Ghost) + Danger. Три размера. Нет скруглений.
Варианты
Размеры
<!-- Primary --> <button class="btn btn--primary">Оформить заказ</button> <!-- Secondary --> <button class="btn btn--secondary">Подробнее</button> <!-- Ghost --> <button class="btn btn--ghost">Отмена</button> <!-- Danger --> <button class="btn btn--danger">Удалить</button> <!-- Размеры: добавь btn--sm или btn--lg --> <button class="btn btn--primary btn--sm">Маленькая</button> <button class="btn btn--primary btn--lg">Большая</button> <!-- Ширина 100% --> <button class="btn btn--primary btn--full">Рассчитать стоимость</button>
Статусы
Используются для маркировки состояния задач, проектов, заказов.
| Класс | Контекст |
|---|---|
.badge--production | Запущено, работает в продакшне |
.badge--prototype | Прототип, тестирование |
.badge--wip | В работе, ещё не завершено |
.badge--concept | Концепт, идея, не утверждено |
.badge--error | Ошибка, требует внимания |
<span class="badge badge--production">Production</span> <span class="badge badge--prototype">Prototype</span> <span class="badge badge--wip">In Progress</span> <span class="badge badge--concept">Concept</span> <span class="badge badge--error">Error</span>
Формы
Input, Select, Label. Фокус — accent-border. Ошибки — красная граница.
<!-- Поле с лейблом -->
<div class="field">
<label class="field__label">Тираж</label>
<input class="input" type="text" placeholder="Например, 500 шт.">
<span class="field__hint">Минимум 50 штук</span>
</div>
<!-- Select -->
<div class="field">
<label class="field__label">Формат</label>
<select class="select">
<option>A4 (210 × 297 мм)</option>
<option>A5 (148 × 210 мм)</option>
</select>
</div>
<!-- Ошибка -->
<div class="field">
<label class="field__label">Email</label>
<input class="input input--error" type="email">
<span class="field__hint field__hint--error">Введите корректный email</span>
</div>
Карточки
Базовый блок для каталога, сервисов, списков проектов. Hover: border → accent, bg → surface.
Правая карточка — hover-состояние
<div class="card">
<div class="card__name">Визитки</div>
<div class="card__desc">Офсетная печать, от 50 шт.</div>
<div class="card__footer">
<span class="badge badge--production">В наличии</span>
</div>
</div>
Калькуляторы на сайте
Промо-калькуляторы на страницах услуг. Позволяют пользователю рассчитать стоимость прямо на сайте без перехода в корзину.
Структура
| Блок | Описание |
|---|---|
.calc | Корневой контейнер калькулятора |
.calc__title | Заголовок — название услуги |
.calc__fields | Группа полей выбора параметров |
.calc__field | Одно поле: лейбл + контрол |
.calc__result | Блок итоговой стоимости |
.calc__price | Цена — крупный акцентный текст |
.calc__action | Кнопка перехода к заказу |
Order Form · живой прототип
Исходник: experiments/order-form/
Допустимые контролы в полях
| Тип | Когда использовать |
|---|---|
select | Фиксированный список значений (тираж, формат, бумага) |
input[type=number] | Произвольное число (тираж вручную, размер) |
radio-группа | 2–4 варианта, нужна визуальная ясность (ламинация) |
checkbox | Добавочные опции (скругление, пробивка) |
Выпадающие списки
Кастомный компонент выбора параметров заказа. Шрифт — Roboto. Угловой, 1px граница. Пять вариантов под разные задачи.
Когда какой вариант использовать
| Вариант | Когда использовать | Не использовать когда |
|---|---|---|
Basic |
Простой выбор: формат, бумага, ламинация. До 6 опций без цен. | Нужно показать цену или тираж |
With Description |
Есть превью-картинка и подпись. Услуги с визуальной разницей (форм-фактор). | Нет изображений, больше 5 опций |
Table 3-col |
Тираж + единица + цена. Когда важна единица измерения (шт/м²/пог.м). | Единица везде одинаковая — используй 2-col |
Table 2-col |
Тираж + цена. Единица одна для всех опций. Компактнее 3-col. | Нужен бейдж РЕКОМЕНДУЕМ по центру — используй v12 |
Space-between |
Тираж + цена по краям. Бейдж РЕКОМЕНДУЕМ слева от тиража. | Нет бейджа и нет нужды в space-between верстке |
Basic — простой список
| Класс | Описание |
|---|---|
.cd | Корневой элемент, position: relative |
.cd__trigger | Кнопка-триггер с chevron-стрелкой |
.cd__list | Выпадающий список (display: none → block при .open) |
.cd__option | Одна опция списка |
.cd__option.selected | Выбранная опция (background: primary-50) |
.cd.open | Открытое состояние — добавляется JS |
<div class="cd">
<div class="cd__trigger">
<span class="cd__label">Стандарт, 90×50</span>
</div>
<div class="cd__list">
<div class="cd__option"><span class="cd__option-label">Стандарт, 90×50</span></div>
<div class="cd__option"><span class="cd__option-label">Евро, 85×55</span></div>
<div class="cd__option"><span class="cd__option-label">Мини, 70×40</span></div>
</div>
</div>
With Description — с превью и описанием
| Класс | Описание |
|---|---|
.cd--desc | Модификатор: высота 64px, align-items: flex-start |
.cd__thumb | Превью слева — 56×full, background: grey-100 |
.cd__option-body | Текстовый блок: title + desc |
.cd__price-addon | Цена справа, margin-left: auto |
<div class="cd cd--desc">
<div class="cd__trigger">
<div class="cd__thumb"><img src="..." alt=""></div>
<div class="cd__option-body">
<span class="cd__option-title">Стандарт</span>
<span class="cd__option-desc">90 × 50 мм</span>
</div>
<span class="cd__price-addon">от 990 ₽</span>
</div>
<div class="cd__list">
<div class="cd__option">
<div class="cd__thumb"><img src="..." alt=""></div>
<div class="cd__option-body">
<span class="cd__option-title">Стандарт</span>
<span class="cd__option-desc">90 × 50 мм</span>
</div>
<span class="cd__price-addon">от 990 ₽</span>
</div>
</div>
</div>
Table 3-col — тираж / единица / цена
| Класс | Описание |
|---|---|
.cd--table | Модификатор: grid 3 колонки, ширина 360px |
.cd-tbl-head | Шапка колонок (Тираж / Единица / Цена) |
.cd__tbl-qty | Значение тиража, font-weight: 500 |
.cd__tbl-unit | Единица измерения, grey-400 |
.cd__tbl-total | Актуальная цена, font-weight: 500 |
.cd__tbl-cross | Зачёркнутая старая цена, grey-300 |
<div class="cd cd--table">
<div class="cd-tbl-head"><span>Тираж</span><span>Единица</span><span>Цена ↓</span></div>
<div class="cd__trigger">
<span class="cd__tbl-qty">100 шт</span>
<span class="cd__tbl-unit">шт</span>
<div class="cd__tbl-price">
<div class="cd__tbl-price-row">
<span class="cd__tbl-total">4 500 ₽</span>
</div>
</div>
</div>
<div class="cd__list">
<div class="cd__option">
<span class="cd__tbl-qty">100 шт</span>
<span class="cd__tbl-unit">шт</span>
<div class="cd__tbl-price">
<div class="cd__tbl-price-row">
<span class="cd__tbl-total">4 500 ₽</span>
<span class="cd__tbl-cross">5 200 ₽</span>
</div>
</div>
</div>
</div>
</div>
Table 2-col — тираж / цена (grid)
| Класс | Описание |
|---|---|
.cd--tbl2 | Модификатор: grid 70px + 1fr, ширина 280px |
.cd-tbl2-head | Шапка двух колонок |
.cd__tbl2-qty | Тираж, font-weight: 500 |
.cd__tbl2-price | Цена, grey-500 |
.cd__badge | Бейдж «РЕКОМЕНДУЕМ», зелёный #22c55e |
<div class="cd cd--tbl2">
<div class="cd-tbl2-head"><span>Тираж</span><span>Цена ↓</span></div>
<div class="cd__trigger">
<span class="cd__tbl2-qty">100 шт</span>
<span class="cd__tbl2-price">4 500 <span class="cd__tbl2-curr">₽</span></span>
</div>
<div class="cd__list">
<div class="cd__option selected">
<span class="cd__tbl2-qty">100 шт</span>
<span class="cd__tbl2-price">4 500 <span class="cd__tbl2-curr">₽</span></span>
</div>
<div class="cd__option">
<span class="cd__tbl2-qty">
<span class="cd__badge">РЕКОМЕНДУЕМ</span> 250 шт
</span>
<span class="cd__tbl2-price">7 800 <span class="cd__tbl2-curr">₽</span></span>
</div>
</div>
</div>
Space-between — тираж и цена по краям
| Класс | Описание |
|---|---|
.cd--v12 | Модификатор: flex justify-content: space-between |
inline flex header | Шапка через inline-style space-between (не grid) |
Все варианты в деталях: experiments/dropdowns/
<div class="cd cd--v12">
<div class="cd--v12 cd-v12-head">
<span class="cd-v12-head__left">Тираж</span>
<span>Цена ↓</span>
</div>
<div class="cd__trigger">
<span class="cd__tbl2-qty">100 шт</span>
<span class="cd__tbl2-price">4 500 <span class="cd__tbl2-curr">₽</span></span>
</div>
<div class="cd__list">
<div class="cd__option">
<span class="cd__tbl2-qty"><span class="cd__badge">РЕКОМЕНДУЕМ</span> 100 шт</span>
<span class="cd__tbl2-price">4 500 <span class="cd__tbl2-curr">₽</span></span>
</div>
</div>
</div>
Карточка даты
Используется для выбора даты готовности заказа. Шрифт — Roboto. Три карточки в ряд (Atom → Molecule). Цена + срок + опциональная скидка.
Состояния
Date Selection Grid — organism
| Класс | Описание |
|---|---|
.dates-grid | Grid-контейнер, 3 колонки, gap: 8px |
.date-card | Карточка: border 1px grey-200, flex col |
.date-card.selected | Выбранная: border-color primary-400 |
.price | Цена: 14px, font-weight 600, grey-700 |
.when | Срок: 11px, grey-400 |
.dc-badge | Скидка: absolute, top-right, red #ef4444 |
<!-- Grid из 3 карточек -->
<div class="dates-grid">
<div class="date-card selected">
<span class="date-card__price">4 500 <span class="date-card__price-curr">₽</span></span>
<span class="date-card__when">За 1 час</span>
</div>
<div class="date-card">
<span class="date-card__price">3 800 <span class="date-card__price-curr">₽</span></span>
<span class="date-card__when">Завтра</span>
<span class="date-card__badge">−15%</span>
</div>
<div class="date-card">
<span class="date-card__price">2 900 <span class="date-card__price-curr">₽</span></span>
<span class="date-card__when">18 марта</span>
</div>
</div>
Stepper
Счётчик для ручного ввода тиража. Используется когда нет фиксированных вариантов или нужен точный ввод числа.
Демо
| Класс | Описание |
|---|---|
.stepper | Обёртка: inline-flex, border 1px grey-200 |
.stepper__btn | Кнопки − и +, 36×36px. Hover: primary-100 |
.stepper__val | Числовой input, 56px, border по бокам |
<div class="stepper"> <button class="stepper__btn" onclick="this.nextElementSibling.stepDown()">−</button> <input class="stepper__val" type="number" value="500" min="1"> <button class="stepper__btn" onclick="this.previousElementSibling.stepUp()">+</button> </div>
Addon Toggle
Добавление/удаление опциональных услуг к заказу. Четыре состояния: недоступно, доступно, добавлено, удаление.
Состояния
Последний — hover-состояние активного аддона
| Класс | Состояние | Описание |
|---|---|---|
.addon--empty | Недоступно | Серый фон, курсор default |
.addon--add | Доступно | Белый фон, hover: border primary |
.addon--active | Добавлено | Border primary, фон primary-50 |
.addon--active:hover | Удаление | Border red, фон #fff5f5 |
<div class="addon addon--add"> <span class="addon__icon">+</span> <span class="addon__label">Ламинация матовая</span> <span class="addon__price">+320 ₽</span> </div> <!-- Добавлено --> <div class="addon addon--active"> <span class="addon__icon">✓</span> <span class="addon__label">Ламинация матовая</span> <span class="addon__price">+320 ₽</span> </div>
Сетка
CSS Grid с auto-fill. Gap — 12px стандартный, 8px плотный.
2 колонки
3 колонки
4 колонки
Контейнеры
Ширина контента ограничивается по контексту. Нет единого универсального контейнера — ширина зависит от задачи.
| Имя | max-width | Контекст |
|---|---|---|
.page (demo) |
900px | Индексные страницы прототипов |
.ds-main |
880px | Документация дизайн-системы |
.case-container |
800px | Кейс-страницы портфолио |
.container |
1200px | Основной сайт oqprint.ru / copy.spb.ru |
| Мобильные поля | padding: 0 24px | Горизонтальный padding до 600px |
Changelog
История изменений дизайн-системы.
| Версия | Дата | Изменения |
|---|---|---|
1.0.0 |
Март 2026 | Первый релиз. Foundation: цвета, типографика, отступы, границы, анимация. Components: Button, Badge, Form, Card, Custom Dropdown (5 вариантов), Date Card, Stepper, Addon Toggle. shared/components.css — единый CSS-файл. |