Темизация блоков
Компонент поставляет разметочный слой для типов блоков: ширину контента, вертикальный ритм секций и набор токенов, которыми блок меряет отступы и цвета. Шрифты, кнопки и типографику он не трогает — их даёт тема, и переопределять их значило бы драться с ней на каждой странице.
Два файла, и именно в таком порядке:
| Файл | Что это |
|---|---|
pb.blocks.css | Контракт: токены, ширина контента, ритм секций. На нём стоит каждый тип блока. |
pb.starter.css | Разметка поставочных типов плюс pb-tone--* и pb-grid--*, которыми может пользоваться любой блок. |
Порядок важен — pb.blocks.css объявляет токены, на которых стоит pb.starter.css. Поэтому styleUrls() возвращает список, а не один адрес.
Файлов два, а не один, чтобы тема могла заменить разметку поставочных блоков и сохранить ритм: выбрасываете pb.starter.css, оставляете pb.blocks.css — и ваши собственные блоки продолжают становиться в тот же ритм, что и всё остальное.
Обычно подключать их руками не надо
На обычной странице MODX слой подключается сам — см. Системные настройки. Тег {pb_styles()} нужен только в шаблоне, который рисует роутер компонента.
Контракт разметки
<div class="pb-page">
<section class="pb-section pb-cards">
<div class="pb-section__inner">...</div>
</section>
</div>Работу делают три класса:
.pb-page— обёртка. Единственное место, где объявлены токены..pb-section— вертикальный ритм. Берёт половину--pb-section-gapв padding сверху и снизу, а не margin между соседями: так у секции с фоном есть свои внутренние поля, а фоны двух соседних секций смыкаются встык..pb-section__inner— колонка контента:max-width: var(--pb-content-max), по центру, с--pb-gutterпо бокам. Фон ставьте на секцию — он дотянется до края окна, а содержимое останется в колонке.
Дальше pb-{ключ} по ключу блока и BEM под ним — .pb-cards__grid, .pb-hero__media, .pb-faq__question.
У первого и последнего потомка .pb-section__inner внешние margin обнулены — иначе заголовок с margin темы съедает padding секции и ритм плывёт. Оба правила через :where(), то есть с нулевой специфичностью: любой обычный селектор в стилях вашего блока их перебьёт.
Модификаторы секции
| Класс | Что делает |
|---|---|
.pb-section--narrow | Колонка сужается до --pb-content-narrow |
.pb-section--wide | Колонка расширяется до --pb-content-wide |
.pb-section--bleed | Ни колонки, ни боковых полей — для карты, слайдера, большой картинки |
.pb-section--flush | Без вертикальных полей, чтобы соседние блоки сомкнулись |
Токены
Объявлены на .pb-page в pb.blocks.css:
| Токен | По умолчанию |
|---|---|
--pb-content-max | 1200px |
--pb-content-narrow | 48rem |
--pb-content-wide | 1600px |
--pb-section-gap | 5rem (3rem ниже 48rem) |
--pb-gutter | 1.25rem |
--pb-gap | 1.5rem (1rem ниже 48rem) |
--pb-radius | 0.5rem |
--pb-accent | currentColor |
--pb-muted | 65% от currentColor |
--pb-surface | 5% от currentColor |
--pb-border | 1px solid, 18% от currentColor |
pb.starter.css добавляет ещё один: --pb-surface-strong, 12% от currentColor.
Цвета выведены из currentColor намеренно: блок наследует цвет текста темы вместо того, чтобы приносить свою палитру. Поэтому одна и та же разметка работает и на светлой теме, и на тёмной, и инвертировать на ней ничего не надо.
Переопределение
Задайте токен заново тем же селектором, из своего css:
.pb-page {
--pb-content-max: 1100px;
--pb-section-gap: 4rem;
--pb-surface: #f5f5f4;
}Почему .pb-page, а не :root
На :root тема сайта и компонент пишут в одно и то же место, и то, как выглядит страница, начинает решать порядок подключения файлов. На обёртке вы переопределяете осознанно — тем же селектором.
И это правило победит независимо от порядка подключения: весь слой лежит в @layer pageblocks, а неслоёное правило сильнее любого слоя. Поэтому для перетемизации никогда не нужно править файлы компонента — обновление их перезапишет и унесёт правки с собой.
То же касается не только токенов, но и отдельного правила: обычный неслоёный селектор в вашей теме перебивает слой без !important и без наращивания специфичности.
Свой класс на обёртке
Нужен только если тема цепляется за контейнер своими селекторами. Обёртка — это чанк pageblocks.blocks.wrapper, который pbBlocks берёт, когда &tplWrapper не указан. Скопируйте его под своим именем, добавьте класс и передайте:
{pbBlocks tplWrapper='my.page.wrapper'}Править поставочный чанк ради этого не надо: для переопределения токена он не нужен, а проверка при обновлении считает отредактированный дефолт вашим и больше его не трогает.
Потеряли обёртку — потеряли токены
Передавайте &tplWrapper=`` только если страницу уже оборачивает сам шаблон сайта и токены вы объявили сами. Без .pb-page токенов на странице нет вообще, и секции каталога расползаются по всей ширине окна.
Та же ловушка — рендер блока прямо из Fenom через {$block->render()}: этот вывод не попадает внутрь обёртки, пока вы его туда не поместите.
Утилиты для любого блока
Из pb.starter.css, то есть доступны и вашим собственным типам:
| Класс | Что делает |
|---|---|
.pb-tone--surface | Фон --pb-surface |
.pb-tone--accent | Фон --pb-surface-strong |
.pb-grid--2 / --3 / --4 | Сетка ровно в 2, 3 или 4 равные колонки с шагом --pb-gap |
У сеток фиксированное число колонок, а не auto-fit: редактор выбирает «три колонки» и ждёт три, а не столько, сколько уместилось. Колонки заданы как minmax(0, 1fr), а не 1fr — иначе одно длинное слово или широкая картинка растягивает свою колонку и сетка перестаёт быть равномерной.
Все три сворачиваются в одну колонку ниже 48rem. В промежутке от 48.0625rem до 64rem.pb-grid--4 становится двухколоночной: четыре колонки на планшете нечитаемы, а три ещё держатся.
Как выключить слой
pageblocks_load_styles — единственный выключатель, и он же ответ на «стили блоков беру на себя». Выключено — styleUrls() возвращает пустой список, а {pb_styles()} пустую строку.
Выключили — токенов тоже нет
Поставочные типы блоков построены на этих токенах. Выключите слой — и вашей теме придётся объявить --pb-content-max, --pb-section-gap, --pb-gap и остальные на .pb-page самой, иначе поставочным блокам нечем себя мерить. Чтобы изменить несколько значений, их надо переопределить — выключатель для этого не нужен.