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 | Колонки |

    |----------|---------|

    | &lt; 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 | Колонки |

    |----------|---------|

    | &lt; 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. Критерии приёмки


    - [ ] На ширине &lt; 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                       — живая документация