Skip to content
PageBuilder
Визуальный конструктор секций для MODX 3: черновик и публикация без перезаписи content ресурса
  1. Компоненты
  2. PageBuilder
  3. Вывод на сайте
  4. Дизайн-система

Дизайн-система (фронт)

Стили секций на сайте не завязаны на PrimeVue в менеджере. Chunks выводят разметку с префиксом pb-, а pagebuilder-sections.css задаёт сетку, шрифты и токены внутри .pb-page.

Подключение CSS и JS

Сниппет PageBuilder вызывает pbRegisterFrontendAssets() при pagebuilder_load_frontend_css = 1 (или &load_css=1``). Файлы регистрируются через regClientCSS с query ?v= по версии файла.

Параметр / настройкаПо умолчаниюЧто делает
pagebuilder_load_frontend_css1Глобально включает CSS сниппета
load_cssиз настройкиПереопределяет подключение на одном вызове
wrap_pageкак load_cssОборачивает HTML в <div class="pb-page">

Отключить стили на странице: [[!PageBuilder? &load_css=0]]. Обёртку можно оставить: &wrap_page=1`` при load_css=0, если токены задаёте сами.

Вместе с CSS подключается pagebuilder-sections.js (если файл есть в составе дополнения). Скрипт инициализирует карусели (data-pb-carousel) и вкладки (data-pb-tabs) внутри .pb-page.

Подробнее про вывод: Вывод на сайте, параметры сниппета: PageBuilder → load_css.

Файлы стилей

Путь от корня сайта: assets/components/pagebuilder/css/.

ФайлКогда грузится
pagebuilder-sections.cssВсегда при load_css=1
pagebuilder-sections-pro.cssПри флаге pro
pagebuilder-commerce.cssПри флаге pro (product-card, spotlight, promo)

Pro и commerce CSS не подключаются на Free-сборке, даже если chunk секции лежит в теме.

Обёртка .pb-page

Токены задаются на .pb-page, не на :root. Глобальная тема сайта не перезаписывается, а секции получают свой ритм отступов.

Соседние прямые потомки .pb-page разделяет вертикальный gap:

css
.pb-page > * + * {
  margin-top: var(--pb-section-gap);
}

Внутренний контейнер секции: .pb-section__inner с max-width: var(--pb-content-max) и горизонтальным padding var(--pb-space-inline).

CSS-токены

Значения по умолчанию из pagebuilder-sections.css. Переопределите их в CSS темы на том же селекторе .pb-page.

TokenПо умолчаниюНазначение
--pb-section-gap4remОтступ между секциями
--pb-content-max72remMax-width inner
--pb-space-sm1remSpacer --sm
--pb-space-md2remSpacer --md
--pb-space-lg4remSpacer --lg
--pb-space-xl6remSpacer --xl
--pb-space-inlinevar(--pb-space-sm)Padding .pb-section__inner
--pb-radius0.5remСкругления
--pb-color-textinheritОсновной текст
--pb-color-mutedcolor-mix(...)Вторичный текст
--pb-color-accent#2563ebАкцент, ссылки в prose
--pb-color-surface#fffФон карточек
--pb-color-ink#0f172aТёмный текст на светлом
--pb-color-bordercolor-mix(...)Границы
--pb-color-on-accent#fffТекст на акцентном фоне
--pb-color-danger#dc2626Ошибки форм
--pb-color-danger-bg#fef2f2Фон ошибки
--pb-color-danger-text#991b1bТекст ошибки
--pb-color-success-bg#ecfdf5Фон успеха
--pb-color-success-text#065f46Текст успеха
--pb-shadow-cardдвухслойная теньКарточки, .pb-surface
--pb-button-bgvar(--pb-color-accent)Фон CTA
--pb-button-colorvar(--pb-color-on-accent)Текст CTA
--pb-grid-gap1.5remСетки cards, gallery, stats
--pb-gallery-columns3Колонки gallery на широком экране
--pb-stats-columns4Колонки stats
--pb-hero-overlayrgb(0 0 0 / 45%)Затемнение hero
--pb-avatar-size3remАватары testimonials
--pb-prose-linkvar(--pb-color-accent)Ссылки в richtext
--pb-video-ratio16 / 9 (в Pro CSS)Embed video

--pb-hero-bg задаётся inline на секции (URL фона), а не в блоке .pb-page.

Пример темы

css
.pb-page {
  --pb-color-accent: #059669;
  --pb-content-max: 60rem;
  --pb-section-gap: 2.5rem;
  --pb-space-inline: 1.25rem;
}

BEM

Префикс блоков: pb-. Имя блока совпадает с ключом секции (heropb-hero).

УровеньПаттернПример
Blockpb-{key}pb-hero, pb-faq
Section shellpb-section, pb-section--{key}pb-section--cta
Elementpb-{block}__*pb-hero__title, pb-section__inner
Modifierpb-{block}--*pb-hero--center, pb-spacer--md

На корне секции:

  • class="pb-section pb-section--hero pb-hero …"
  • data-pb-section="hero" для отладки и стилей
  • id="pb-{id}" если в документе задан id секции

Общие примитивы из базового CSS:

КлассНазначение
pb-button, pb-button--smCTA и ссылки-кнопки
pb-headingЗаголовок секции
pb-grid, pb-grid--cardsCSS Grid
pb-surfaceКарточка с тенью
pb-spacer, pb-spacer--mdВертикальный отступ между блоками внутри секции
pb-listing, pb-listing__gridОбёртка каталогов (Pro commerce)
pb-carousel, pb-tabsИнтерактив (Pro + JS)

Spacer: два класса pb-spacer pb-spacer--md, не pb-spacer-md.

Кнопка в hero: pb-hero__button pb-button. Фон hero: CSS var --pb-hero-bg, не отдельный inline background-image без переменной.

Fenom-оболочка секции

Штатный chunk hero (упрощённо):

fenom
{var $heroBg = is_array($background) ? ($background.url ?: '') : ($background ?: '')}
<section class="pb-section pb-section--hero pb-hero{if $alignment == 'center'} pb-hero--center{/if}{if $cssClass} {$cssClass|escape}{/if}"
  data-pb-section="hero"{if $id} id="pb-{$id|escape}"{/if}{if $heroBg} style="--pb-hero-bg: url('{$heroBg|escape}')"{/if}>
  <div class="pb-section__inner pb-hero__inner">
    <h1 class="pb-hero__title">{$title|escape}</h1>
    ...
  </div>
</section>

Переменные chunk:

  • $cssClass из data.cssClass (событие pbOnBeforeRenderSection)
  • $id: id секции в JSON документа
  • поля секции по name из JSON ($title, $background, …)

Свои секции собирайте по тому же шаблону. Чеклист: Разработчик → Определение секции.

Partial pagebuilder_partial_image

Общий chunk для <img> в gallery, testimonials, image и Pro-секциях:

fenom
{include 'pagebuilder_partial_image' image=$item.image alt=$item.alt class='pb-gallery__media'}
ПараметрОписание
imageСтрока URL или массив поля image (url)
altAlt-текст
classCSS-класс на <img>
loadingПо умолчанию lazy

Partial не рендерит тег, если URL пустой.

Escape и ссылки

Тип поляFenom
text, textarea|escape
url в href|pb_href|escape (нормализация MODX-ссылок)
richtext, editorjsHTML редактора без sanitize на фронте

Rich text выводите только если доверяете редакторам с правом сохранения ресурса. Остальной текст экранируйте.

Дополнительный класс через событие

В pbOnBeforeRenderSection можно дописать data.cssClass перед рендером chunk. Chunk добавляет класс на <section>:

php
case 'pbOnBeforeRenderSection':
    $pipeline = $scriptProperties['pipeline'] ?? null;
    if ($pipeline instanceof \PageBuilder\Section\SectionRenderPipeline) {
        $sections = $pipeline->sections();
        if (isset($sections[0])) {
            $sections[0]['data']['cssClass'] = trim(($sections[0]['data']['cssClass'] ?? '') . ' is-promo');
            $pipeline->replaceSection(0, $sections[0]);
        }
    }
    break;

Событие срабатывает только при промахе HTML-кеша сниппета (use_cache=0 для отладки). Подробнее: Менеджер и события.

Интерактив на фронте

pagebuilder-sections.js без зависимостей:

МаркерПоведение
[data-pb-carousel]Слайды в .pb-carousel__track, dots, autoplay при data-pb-autoplay="1"
[data-pb-tabs]Переключение панелей, hash в URL по data-pb-anchor

Учитывается prefers-reduced-motion: reduce (autoplay и smooth scroll отключаются).

Commerce-стили (Pro)

pagebuilder-commerce.css стилизует карточки товаров и блоки витрины: .pb-product-card, .pb-product-spotlight, promo-баннеры. Секции listing часто добавляют pb-listing рядом с блоком (pb-products-grid pb-listing).

Токены те же, что у .pb-page. Перекраска commerce идёт через --pb-color-accent, --pb-color-surface, --pb-shadow-card.

Якоря и sticky header

У секций с id="pb-…" и карточек в listing задан scroll-margin-top: 5.5rem, чтобы sticky-шапка сайта не перекрывала якорь.

Миграция spacer

Класс pb-spacer-md заменён на pb-spacer--md. После апгрейда проверьте кастомные CSS темы и свои chunks.

Связанные страницы