PaniLara система сетки и контейнеров v4.loc
# ТЗ: система сетки и контейнеров v4.loc
Версия: 1.0 (май 2026)
Статус: утверждённая реализация в `templates/good/css/greed.css`
## 1. Назначение и область
**Цель:** единая, предсказуемая вёрстка страниц на **CSS Grid** без JS для раскладки: контейнеры, адаптивные карточные сетки, кабинет (2 колонки), чат (3 колонки), узкая колонка для авторизации.
**Источник правды:**
| Ресурс | Путь |
|--------|------|
| Ядро сетки | `templates/good/css/greed.css` |
| Демо и описание в разметке | `grid.html` |
| Живые примеры | `cabinet.html`, `chat.html`, `login.html`, `schedule.html`, `menu.html` |
| Сборка бандла | `templates/good/css/build-master.ps1` → `master.css` / `master.prod.css` |
**Вне scope сетки (соседние слои):** шапка/меню (`menu.css`), формы (`forms.css`), чат (`chat.css`), карточки демо (`demo.css` — `.card`, `.aside-box`, `.footer-grid`).
---
## 2. Принципы проектирования
| Принцип | Реализация |
|--------|------------|
| Mobile-first | Базовая раскладка — одна колонка; расширение через `@media (min-width: …)` |
| Без JS для layout | Только CSS Grid + container queries |
| Минимальная DOM-обёртка | `main → section → container → контент` |
| Переполнение | У layout-утилит: `min-width: 0` на grid-родителе; у картинок: `max-width: 100%` |
| Высота колонок кабинета/чата | `align-items: stretch` (явно), **не** `align-items: start` у layout-родителя |
| Два типа брейкпоинтов | Viewport (`576/992/1200/1440px`) и layout-порог **`62rem`** (~992px) для кабинета/чата |
| Container queries | `.layout-sidebar`, `.col-narrow-center` — поведение от ширины **контейнера**, не viewport |
---
## 3. Глобальная структура страницы
```html
<body>
<header class="site-header">…</header>
<main>
<section class="section">
<div class="container">…</div>
</section>
</main>
<footer class="site-footer">…</footer>
</body>
```
**`body`:** `display: flex; flex-direction: column; min-height: 100dvh` — футер прижат к низу.
**`main`:** `flex: 1` — растягивается между шапкой и футером.
**Секция:** класс `.section`, вертикальные отступы `padding-block: var(--space-7)` (48px).
---
## 4. Дизайн-токены (обязательные для сетки)
Определяются в `:root` файла `greed.css`:
```css
--container: 1440px;
--container-narrow: 800px;
--container-wide: 1440px;
--container-padding: clamp(12px, 2vw, 24px);
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 24px;
--space-6: 32px;
--space-7: 48px;
--layout-cab-aside: minmax(16rem, 18rem);
```
**Отступы между ячейками grid:** везде `gap: var(--space-4)` (16px), кроме плотных сеток с доп. `margin-top` у `.grid--five` / `.grid--six`.
---
## 5. Контейнеры
Общая формула ширины:
```css
width: min(100% - calc(var(--container-padding) * 2), 100%);
margin-inline: auto;
```
| Класс | `max-width` | Назначение |
|-------|-------------|------------|
| `.container` | `1440px` | Основной контент (шапка, секции, кабинет) |
| `.container-wide` | `1440px` | Алиас того же лимита |
| `.container-narrow` | `800px` | Long-form, узкий текст |
| `.container-fluid` | нет | На всю ширину viewport с теми же боковыми полями |
**Поведение:** контент центрируется; на широких мониторах не растягивается бесконечно. Fluid-полосы — отдельная секция с `.container-fluid` внутри `main` (см. демо на `grid.html`).
---
## 6. Карточные сетки (`.grid`)
Базовый класс:
```css
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr));
gap: var(--space-4);
}
```
Число колонок **не задаётся брейкпоинтами** — подстраивается под ширину контейнера (`auto-fill` + `minmax`).
### Модификаторы
| Класс | `grid-template-columns` | Поведение |
|-------|-------------------------|-----------|
| `.grid-two` | `repeat(auto-fit, minmax(min(360px, 100%), 1fr))` | 2 колонки при достаточной ширине |
| `.grid-three` | `repeat(auto-fit, minmax(min(260px, 100%), 1fr))` | до 3 колонок |
| `.grid-four` | `repeat(auto-fit, minmax(min(220px, 100%), 1fr))` | до 4 колонок |
| `.grid--five` | базовая сетка; **с 1200px** → `repeat(5, minmax(0, 1fr))` | витрина каталога |
| `.grid--six` | базовая сетка; **с 1440px** → `repeat(6, minmax(0, 1fr))` | очень широкие экраны |
**Разметка:**
```html
<div class="grid grid-two">
<article>…</article>
<article>…</article>
</div>
```
Для 2–4 колонок используется **`auto-fit`** (колонки растягиваются, пустых треков нет).
---
## 7. Layout-утилиты
### 7.1 `.layout-pair-equal` — две колонки одной высоты
**Назначение:** сайдбар + основная область (`cabinet.html`, `schedule.html`, `menu.html`).
| Viewport | Колонки |
|----------|---------|
| < 62rem | `1fr` (стек) |
| ≥ 62rem | `var(--layout-cab-aside) minmax(0, 1fr)` |
```css
.layout-pair-equal {
display: grid;
gap: var(--space-4);
align-items: stretch;
grid-template-columns: 1fr;
min-width: 0;
}
@media (min-width: 62rem) {
.layout-pair-equal {
grid-template-columns: var(--layout-cab-aside) minmax(0, 1fr);
}
}
```
**Разметка:**
```html
<div class="container">
<div class="layout-pair-equal">
<aside class="content-box">…</aside>
<section class="content-box">…</section>
</div>
</div>
```
**Правило:** высота ряда = максимуму содержимого; обе `.content-box` визуально одной высоты. Не ставить родителю `align-items: start`.
---
### 7.2 `.layout-trio-chat` — три колонки (профиль + список + диалог)
**Назначение:** `chat.html`.
| Viewport | Колонки |
|----------|---------|
| < 62rem | одна колонка, порядок DOM сверху вниз |
| ≥ 62rem | `repeat(2, var(--layout-cab-aside)) minmax(0, 1fr)` |
Первые два трека **совпадают по ширине** с левой колонкой `.layout-pair-equal`.
```html
<div class="layout-trio-chat">
<aside class="content-box">…</aside>
<nav class="content-box chat-threads">…</nav>
<section class="content-box chat">…</section>
</div>
```
Стили окна переписки — отдельно в `chat.css`.
---
### 7.3 `.layout-sidebar` — контент + сайдбар (container query)
```css
.layout-sidebar {
display: grid;
gap: var(--space-4);
container-type: inline-size;
}
@container (min-width: 900px) {
.layout-sidebar {
grid-template-columns: minmax(0, 1fr) 320px;
}
}
```
Переключение в 2 колонки когда **сам блок** ≥ 900px (не viewport). На мобильном сайдбар в потоке документа, не fixed.
---
### 7.4 `.col-narrow-center` — узкая колонка по центру (login)
```css
.col-narrow-center {
width: min(100%, 420px);
margin-inline: auto;
container-type: inline-size;
container-name: narrow-center;
}
```
**Паттерн:**
```html
<div class="container">
<div class="col-narrow-center">
<div class="form-tint-card">…</div>
</div>
</div>
```
Вложенные карточки форм (`forms.css`):
```css
.form-tint-card {
width: min(100%, 22rem);
margin-inline: auto;
}
```
Без `margin-inline: auto` при `width: 100%` + `max-width` карточка визуально смещается влево на мобильном.
Container query `narrow-center` используется в формах (например, размер заголовка карточки от 24rem).
---
## 8. Вспомогательные блоки
| Класс | Файл | Назначение |
|-------|------|------------|
| `.content-box` | `greed.css` | Рамка + padding колонки кабинета/чата |
| `.aside-box` | `demo.css` | Демо-карточка с рамкой |
| `.prose` | `greed.css` | Типографика внутри контейнера |
| `.card` | `demo.css` | Карточка витрины внутри `.grid` |
`.content-box`:
```css
.content-box {
padding: var(--space-4);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
}
```
---
## 9. Шкала брейкпоинтов (viewport, mobile-first)
Утверждённая шкала (комментарий в `greed.css`, демо в `grid.html`):
| Минимальная ширина | Типичное использование |
|--------------------|-------------------------|
| **576px** | 2 колонки в `.footer-grid` (`demo.css`) |
| **992px** | Десктоп-шапка, горизонтальное меню (`menu.css`) |
| **1200px** | `.grid--five` → ровно 5 колонок |
| **1440px** | `.grid--six` → ровно 6 колонок |
**Отдельный layout-порог (не из этой четвёрки):**
| Порог | Где |
|-------|-----|
| **62rem** (~992px) | `.layout-pair-equal`, `.layout-trio-chat` |
**Container queries:**
| Контейнер | Условие | Эффект |
|-----------|---------|--------|
| `.layout-sidebar` | `min-width: 900px` | контент + sidebar 320px |
| `narrow-center` | `min-width: 24rem` | типографика в `.form-tint-card` (`forms.css`) |
---
## 10. Подключение стилей
**Минимум для страницы с сеткой:**
```html
<link rel="stylesheet" href="/templates/good/css/greed.css">
<link rel="stylesheet" href="/templates/good/css/demo.css">
```
**Продакшен-бандл:**
```powershell
powershell -NoProfile -File "templates/good/css/build-master.ps1" -ExcludeCalendar
```
Порядок в бандле: `greed.css` **первым** — токены и сетка не перебиваются.
---
## 11. Карта страниц → классы сетки
| Страница | Layout / сетка |
|----------|----------------|
| `grid.html` | Все паттерны (демо-референс) |
| `cabinet.html`, `schedule.html` | `.container` → `.layout-pair-equal` |
| `chat.html` | `.container` → `.layout-trio-chat` |
| `login.html` | `.container` → `.col-narrow-center` → `.form-tint-card` |
| `full.html` | `.grid.grid-two` + `.card` |
| Футер (все страницы) | `.container` → `.footer-grid` (2 col @576px, 4 col @1200px) |
---
## 12. Чеклист воспроизведения с нуля
1. Скопировать/воссоздать `:root` токены (`--container*`, `--space-*`, `--layout-cab-aside`, `--container-padding`).
2. Реализовать `box-sizing: border-box` глобально; `body` flex-column + `main { flex: 1 }`.
3. Контейнеры `.container` / `.container-narrow` / `.container-fluid` с формулой `min(100% - 2×padding, 100%)`.
4. `.section` с `padding-block: var(--space-7)`.
5. Базовый `.grid` + модификаторы `grid-two` … `grid-four`, `grid--five`, `grid--six` с media 1200/1440px.
6. `.layout-pair-equal` и `.layout-trio-chat` с порогом **62rem** и `align-items: stretch`.
7. `.layout-sidebar` с `container-type: inline-size` и `@container (min-width: 900px)`.
8. `.col-narrow-center` + container name `narrow-center`.
9. `.content-box` для колонок кабинета/чата.
10. Сверить с `grid.html` в браузере (320px, 576px, 992px, 1200px, 1440px).
11. Проверить `cabinet.html` и `chat.html` — совпадение ширины первых колонок.
12. Проверить `login.html` — карточка строго по центру на мобильном.
---
## 13. Антипаттерны
- `align-items: start` на `.layout-pair-equal` / `.layout-trio-chat` — колонки разной высоты по рамке.
- Фиксированный `min-height` в px/vh для выравнивания колонок кабинета.
- Дублирование DOM для mobile/desktop вместо одной сетки.
- `width: 100%` + `max-width` у вложенной карточки **без** `margin-inline: auto` — визуальный сдвиг влево.
- `<fieldset>` без `min-inline-size: 0` на узких формах — горизонтальный скролл.
- Подмена порога 62rem на 992px в layout-утилитах без согласования с дизайном (сейчас намеренно **rem**, не px viewport).
---
## 14. Критерии приёмки
- [ ] На ширине < 62rem кабинет и чат — одна колонка, порядок как в DOM.
- [ ] На ≥ 62rem кабинет: aside ~16–18rem, main занимает остаток; колонки одной высоты.
- [ ] На ≥ 62rem чат: две узкие колонки равны ширине aside кабинета, третья — `1fr`.
- [ ] `.grid` / `grid-two`…`four` схлопываются без горизонтального скролла на 320px.
- [ ] `.grid--five` / `--six` дают ровно 5/6 колонок только на 1200+/1440+.
- [ ] `.col-narrow-center` и форма login центрированы на мобильном.
- [ ] `.layout-sidebar` переходит в 2 колонки при ширине родителя ≥ 900px, не viewport.
- [ ] Демо `grid.html` открывается и совпадает с описанием выше.
---
## Связанные файлы
```
templates/good/css/greed.css — реализация
templates/good/css/demo.css — .card, .aside-box, .footer-grid
templates/good/css/forms.css — .form-tint-card, container narrow-center
templates/good/css/menu.css — брейкпоинт 992px для шапки
grid.html — живая документация