Skip to content

Темизация блоков ​

Компонент поставляет разметочный слой для типов блоков: ширину контента, вертикальный ритм секций и набор токенов, которыми блок меряет отступы и цвета. Шрифты, кнопки и типографику он не трогает — их даёт тема, и переопределять их значило бы драться с ней на каждой странице.

Два файла, и именно в таком порядке:

ФайлЧто это
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()} нужен только в шаблоне, который рисует роутер компонента.

Контракт разметки ​

html
<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-max1200px
--pb-content-narrow48rem
--pb-content-wide1600px
--pb-section-gap5rem (3rem ниже 48rem)
--pb-gutter1.25rem
--pb-gap1.5rem (1rem ниже 48rem)
--pb-radius0.5rem
--pb-accentcurrentColor
--pb-muted65% от currentColor
--pb-surface5% от currentColor
--pb-border1px solid, 18% от currentColor

pb.starter.css добавляет ещё один: --pb-surface-strong, 12% от currentColor.

Цвета выведены из currentColor намеренно: блок наследует цвет текста темы вместо того, чтобы приносить свою палитру. Поэтому одна и та же разметка работает и на светлой теме, и на тёмной, и инвертировать на ней ничего не надо.

Переопределение ​

Задайте токен заново тем же селектором, из своего css:

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 не указан. Скопируйте его под своим именем, добавьте класс и передайте:

fenom
{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 самой, иначе поставочным блокам нечем себя мерить. Чтобы изменить несколько значений, их надо переопределить — выключатель для этого не нужен.

© PageBlocks 2019-present