Инъекция CSS

Web Host использует многослойный конвейер инъекции, чтобы придать дочерним iframe ту же визуальную тему, что и у самого хоста. Поскольку iframe не наследуют CSS от родительского документа, хост заново вставляет каждый стилевой ресурс явным образом в srcdoc потомка. Каждый слой переключается независимо через ProxyConfig.

Эта страница документирует конвейер инъекции, все доступные флаги и то, как настраивать стили на глобальном уровне, на уровне оболочки хоста или отдельной страницы. Это канонический справочник по CSS-флагам proxy.injections и их рантайм-умолчаниям — авторские документы, показывающие рекомендуемые явные значения, ссылаются сюда. Руководство по оформлению для разработчиков (токены CSS-переменных, сопоставление с Tailwind, шаблоны веб-компонентов) см. в Оформление.

Матрица доставки CSS

Фасад предоставляет оформление через три области — global (custom_css, css_variables, icon_sets), host (host_custom_css, host_css_variables, host_icon_sets) и children (children_custom_css, children_css_variables). Web Host составляет их для каждой поверхности. Всё нижеследующее подчиняется двум правилам:

  • Пользовательские CSS-свойства (*_css_variables) наследуются на хост веб-компонента и пробрасываются через его внутренний корень с принудительной темой. WippyElement перечисляет каждое действующее настроенное имя, поэтому локальные умолчания темы не могут его сбросить. Это универсально и не зависит от customCss.
  • Правила CSS-селекторов (*_custom_css) не каскадируются через границу shadow DOM. Они действуют только там, куда вставлены: в документ каждого iframe для view.page и — начиная с Web Host 1.0.43 — в каждый shadow root view.component (отключается флагом customCss компонента). До 1.0.43 туда доходили только переменные.
Настройка фасада Что доставляет Документ оболочки хоста iframe view.page shadow root view.component
custom_css (global) правила с селекторами ✓ вставляется ✓ вставляется¹ ✓ вставляется (1.0.43+, с отключением)¹
css_variables (global) пользовательские свойства ✓ действующие блоки режимов ✓ действующие блоки режимов ✓ наследуется + пробрасывается
host_custom_css (host) правила с селекторами ✓ вставляется ✗ ✗
host_css_variables (host) пользовательские свойства ✓ :root ✗ только веб-компоненты, смонтированные в хосте²
children_custom_css (children) правила с селекторами ✗ ✓ вставляется¹ ✓ вставляется (1.0.43+, с отключением)¹
children_css_variables (children) пользовательские свойства ✗ ✓ :root только веб-компоненты страницы²

¹ Web Host составляет то, что получает потомок: и iframe view.page, и view.component получают пользовательский CSS global + children, слитый в одну таблицу (children_custom_css добавляется после custom_css). Флаг customCss — это переключатель, а не буквальная инъекция одной конкретной области.

² Веб-компонент наследует пользовательские свойства из :root того места, где он смонтирован: веб-компонент в оболочке хоста наследует переменные global + host из документа хоста; веб-компонент внутри view.page наследует переменные global + children из этого iframe. Вставляемый в него пользовательский CSS — всегда область children (global + children). Держите общее оформление в custom_css / css_variables (global) — они доходят до каждой поверхности независимо от места монтирования.

Поддержка файлов fs://: шесть перечисленных настроек оформления принимают значение fs://<path>, разрешаемое во время запроса из файловой системы content_fs — см. Фасад → Переиспользование оформления фасада на страницах вне Web Host. icon_sets / host_icon_sets и все JSON-параметры, не относящиеся к оформлению, задаются только инлайн.

Если переопределений больше нескольких, держите CSS и JSON в отдельных файлах за content_fs и ссылайтесь на них через fs://. Так ресурсы темы остаются пригодными к рецензированию и переиспользованию. Не подменяйте это на file://: это механизм инлайнинга во время загрузки, а не контракт оформления фасада во время запроса.

Конвейер инъекции

Стили вставляются в такой логической слоистости. Первые четыре слоя — обычные элементы <style>/<link>; последние два (customCSS и cssVariables) — нет: они помещаются в adoptedStyleSheets документа iframe (см. Механизм переопределения ниже), поэтому всегда побеждают независимо от порядка в исходном <head>:

Короткий ответ на вопрос о «порядке инъекции CSS»: конвейер стилей iframe view.page — это themeConfig → primevue/tailwind → iframe → markdown → customVariables → customCss в порядке логического каскада. Не путайте это со слоями приоритета конфигурации, такими как тема фасада → config_overrides страницы → рантайм-переопределение; они определяют, какие значения станут customVariables/customCss, а не где итоговые стили окажутся в каскаде iframe.

1. theme-config.css      — пользовательские CSS-свойства (--p-primary-*, --p-surface-*, --p-secondary-*)
2. primevue.css          — стили компонентов PrimeVue, привязанные к этим переменным
   tailwind.css          — утилитарные классы Tailwind (тот же бандл, что и primevue.css)
3. iframe.css            — оформление полос прокрутки по теме по умолчанию (историческое имя; сброса вёрстки iframe нет)
4. markdown.css          — стили отрисовки .data-body для содержимого Markdown
5. cssVariables          — действующая база + блоки Auto/принудительных режимов из AppConfig.theming.global.cssVariables (adopted stylesheet)
6. customCSS             — сырой CSS из проецируемого в потомка AppConfig.theming.global.customCSS (adopted stylesheet)

Этот список показывает логический порядок переопределения, а не буквальный порядок вставки в <head>. В продакшн-прокси два слоя adopted-таблиц (cssVariables, затем customCSS) фактически вставляются до theme-config.css и PrimeVue, но всё равно их переопределяют — потому что adopted-таблицы каскадируются после всех элементов <style>/<link> документа. См. Механизм переопределения.

Каждый дочерний iframe получает независимую копию всех стилей, а не наследование через каскад. Хост и все потомки отрисовываются с одной и той же визуальной темой, потому что получают идентичные вставляемые ресурсы из одного источника.

Флаги ProxyConfig.injections.css

Эти вложенные флаги записываются в нижнем camelCase и в YAML реестра бэкенда, и во фронтенд-файле package.json под wippy.proxy.injections.css. Имена требований фасада используют свои документированные имена в snake_case, тогда как поля реестра следуют собственной схеме. Вложенные объекты прокси передаются без преобразования ключей. YAML побеждает по каждому вложенному ключу. См. Микрофронтенд-приложения (view.page) § Переопределение прокси оператором.

meta:
  type: view.page
  # ...
  proxy:
    enabled: true
    injections:
      css:
        themeConfig: true
        primevue: true
        customCss: true
      tailwindConfig: false
{
  "wippy": {
    "proxy": {
      "injections": {
        "css": {
          "themeConfig": true,
          "iframe": true,
          "primevue": true,
          "markdown": true,
          "customCss": true,
          "customVariables": true
        },
        "tailwindConfig": true,
        "resizeObserver": true,
        "preventLinkClicks": true,
        "iconifyIcons": true,
        "refreshWhenVisible": true,
        "historyPolyfill": true,
        "errorCapture": true
      }
    }
  }
}

CSS-флаги

Флаг По умолчанию Что вставляет
themeConfig true theme-config.css — все --p-primary-*, --p-surface-*, --p-secondary-* и семантические переменные PrimeVue. Отключение полностью убирает наследование темы.
iframe true iframe.css — оформление полос прокрутки по теме по умолчанию. Имя историческое и не подразумевает правил вёрстки iframe. Держите включённым для каждой страницы ради единообразия полос прокрутки.
primevue true primevue.css + tailwind.css — стили компонентов PrimeVue и утилиты Tailwind v3 (~455 КБ вместе). Отключайте, только пока весь артефакт не содержит продуктового интерфейса, похожего на PrimeVue. Сам по себе выбор фреймворка исключением не является.
markdown true markdown.css — стили отрисовки markdown для .data-body, используемые при показе артефактов чата.
customCss true Строка customCSS из проецируемого в потомка AppConfig.theming.global.
customVariables true Проецируемая в потомка карта cssVariables, скомпилированная как действующая база, блоки Auto-light/dark и принудительных Light/Dark для каждого настроенного имени пользовательского свойства.

Отдельного флага для шрифтов нет. Google Fonts доставляются через theming.global.customCSS (правило @import), которое iframe вставляет существующим флагом customCss.

Флаги инъекции, не относящиеся к CSS

Эти флаги расположены рядом с css в блоке injections:

Флаг По умолчанию Что делает
tailwindConfig true Предоставляет window.tailwind.config приложениям, использующим рантайм Tailwind с CDN (<script src="https://cdn.tailwindcss.com">). Не нужен для сборок Vite, компилирующих Tailwind во время сборки.
resizeObserver true Наблюдает за body дочернего документа и отправляет обновления размера хосту. Это ретрансляция размера body, а не полифил браузерного API.
preventLinkClicks true Перехватывает все клики по <a> внутри iframe и классифицирует их через host.classifyLink() перед переходом. Полезно для страниц с внешним Markdown-содержимым, которое может содержать ссылки, ведущие в хост.
iconifyIcons true Вставляет зарегистрированные наборы иконок Iconify, чтобы элементы <iconify-icon> работали офлайн.
refreshWhenVisible true Уведомляет потомка, когда ранее скрытый iframe снова становится видимым.
historyPolyfill true Сегодня ничего не делает. Полифил history намеренно отключён для srcdoc-iframe (window.location неконфигурируемо), поэтому флаг не имеет рантайм-эффекта. Вместо этого среда выполнения всегда устанавливает страж history, который подменяет методы window.history заглушками и предупреждает о необходимости маршрутизации через memory-history — приложения обязаны использовать режим memory (например, memory history из createAppRouter). Установка этого флага не делает смену маршрутов SPA наблюдаемой для хоста.
errorCapture true Устанавливает обработчики window.onerror и window.onunhandledrejection, пересылающие неперехваченные ошибки хосту через logger.captureException. Включайте в продакшене для централизованного сбора ошибок.

Если страница опускает wippy.proxy.injections, прокси iframe использует разрешительные рантайм-умолчания и включает большинство инъекций. Микрофронтенд-приложениям на Vite всё же стоит объявлять явные значения, на которые они опираются, чтобы при рецензировании пакета было видно, ожидает ли приложение CSS хоста, перехват ссылок, отчёт о размере body или перехват ошибок.

Отключение ненужных инъекций

Страница может отключить инъекцию PrimeVue, только пока она не содержит стандартных продуктовых элементов управления или поверхностей, которые предоставляет PrimeVue. Страница только с canvas/SVG/графиком допустима. Как только на ней появляется кнопка, поле ввода, форма, таблица, диалог, меню, тег, подсказка или элемент обратной связи, используйте PrimeVue и оставьте инъекцию включённой; сам по себе выбор фреймворка — не причина для отказа.

{
  "wippy": {
    "proxy": {
      "injections": {
        "css": {
          "primevue": false,
          "themeConfig": false
        }
      }
    }
  }
}

При обоих отключённых флагах страница по-прежнему получает customCSS, cssVariables и iframe.css (сброс полос прокрутки), если только они тоже не отключены. API прокси, ретрансляция состояния и мост WebSocket от CSS-флагов не зависят.

Веб-компоненты: пользовательский CSS фасада + hostCssKeys

Веб-компоненты не проходят через конвейер инъекции iframe. Тему в shadow root компонента приносят два канала:

  • Настроенные переменные + пользовательский CSS фасада. @wippy-fe/webcomponent-core перечисляет каждое действующее имя пользовательского свойства global/children/page, включая имена под @light / @dark, и устанавливает универсальный мост наследования после платформенных умолчаний темы. Затем он устанавливает составленный customCSS global + children как финальный слой. customCss: false отключает только слой правил с селекторами; распространение настроенных переменных он не отключает.
  • Платформенные CSS-ресурсы (hostCssKeys). theme-config.css, PrimeVue, markdown и стили iframe/полос прокрутки — это статические ресурсы бандла, а не настроенный CSS фасада. Компонент запрашивает нужные ему по URL через wippyConfig.hostCssKeys (или загружает их по месту через loadCss() из @wippy-fe/proxy), и среда выполнения вставляет их в shadow root.
static get wippyConfig() {
  return {
    hostCssKeys: ['themeConfigUrl', 'primeVueCssUrl'] as const,
  }
}

Для обычной разработки компонентов используйте декларативный hostCssKeys. loadCss() — аварийный люк для интеграций; никогда не переписывайте смонтированное shadow-дерево через shadowRoot.innerHTML.

Доступные ключи hostCss:

Ключ Содержимое Влияние на бандл
hostCss.themeConfigUrl CSS-переменные (--p-primary-*, светлая + тёмная) Небольшое (~5 КБ)
hostCss.primeVueCssUrl Компоненты PrimeVue + утилиты Tailwind Большое (~455 КБ)
hostCss.markdownCssUrl Стили отрисовки markdown для .data-body Небольшое
hostCss.iframeCssUrl Оформление полос прокрутки с использованием --p-surface-* Крошечное
hostCss.preflightCssUrl Базовый сброс preflight от Tailwind/PrimeVue (normalize/reset) Небольшое

Веб-компоненту, которому нужна отрисовка, точно соответствующая хосту, может понадобиться явно загрузить hostCss.preflightCssUrl через loadCss(), поскольку базовый сброс preflight хоста не пересекает границу shadow DOM.

О том, какие ключи запрашивать и когда — включая дерево решений для баланса точности стилей и размера бандла Shadow DOM — см. Оформление веб-компонентов § дерево решений hostCssKeys.

Проекция AppConfig.theming

Конфигурация фасада предоставляет три области оформления: theming.global, theming.host и theming.children. Прежде чем iframe страницы получит свою дочернюю конфигурацию, хост проецирует действующую дочернюю тему в AppConfig.theming.global. Именно эту дочернюю глобальную область customCss и customVariables вставляют в iframe.

Ключи — это имена CSS-переменных ровно в том виде, в каком они должны появиться в CSS:

// В конфигурации фасада или в полезной нагрузке PostMessage SetConfig.
theming: {
  global: {
    cssVariables: {
      '--p-primary': 'rgb(220, 38, 38)',
      '--p-surface-0': '#0f0f0f',
      '--p-content-border-radius': '2px',
    }
  }
}

Компилятор нормализует ведущие --, сливает базу верхнего уровня с @light / @dark и выпускает действующие блоки Auto-light, Auto-dark, принудительного Light и принудительного Dark в adopted-таблицу iframe. Он не зависит от конкретных переменных: базы палитры, прямые оттенки/алиасы, поверхности, типографика, токены хоста и специфичные для приложения свойства идут одним и тем же путём. Переопределение не зависит от порядка в исходном <head> — см. Механизм переопределения.

Механизм переопределения: adopted-таблицы стилей

customCSS и cssVariables — не обычные элементы <style>/<link> в <head>. Прокси помещает их в adoptedStyleSheets документа iframe (конструируемые таблицы стилей). По правилам каскада CSS adopted-таблицы всегда упорядочиваются после всех документных таблиц <style>/<link> независимо от порядка вставки, поэтому они всегда побеждают theme-config.css, primevue.css, iframe.css и markdown.css. В продакшн-прокси эти пользовательские слои фактически вставляются до theme-config.css и PrimeVue; переопределение всё равно работает, потому что оно обусловлено позицией adopted-таблиц в каскаде, а не порядком в исходном <head>.

Между двумя пользовательскими слоями customCSS переопределяет cssVariables: adopted-таблицы упорядочены сначала cssVariables, затем customCSS, а более поздние adopted-таблицы имеют более высокий приоритет. Если один и тот же токен --p-* задан в обоих, побеждает значение из customCSS.

Три области оформления

Фасад поддерживает три области cssVariables, нацеленные на разные слои отрисовки:

Ключ области Куда вставляется Сценарий использования
theming.global Оболочка хоста и каждый дочерний iframe Брендовые цвета, основная палитра, общие наборы иконок
theming.host Только оболочка хоста Переопределения боковой панели, шапки, чата и заголовка приложения
theming.children Только дочерние iframe CSS-переменные и переопределения CSS только для потомков

Дочерние iframe не получают theming.host или theming.children как отдельные области. Они получают слитый результат для потомков как config.theming.global.

Переопределения на уровне страницы

Отдельные страницы могут переопределять переменные через window.__WIPPY_CONFIG_OVERRIDES__ (задаётся в записи реестра страницы как meta.config_overrides или в package.json как wippy.configOverrides):

window.__WIPPY_CONFIG_OVERRIDES__ = {
  customization: {
    cssVariables: {
      '--p-primary': '#ff6b00',
    },
    customCSS: '.my-page-header { border-radius: 12px; }',
  },
}

Бэкендовый YAML config_overrides.customization — поверхность описания на уровне страницы. Его ключи cssVariables и customCSS проецируются во фронтендовые theming.global.cssVariables и customCSS до того, как страница получит AppConfig, заменяя унаследованные дочерние значения для этой страницы. Поскольку переопределение сливается в theming.global, оно распространяется вниз по всему вложенному поддереву: каждый потомок, встраиваемый страницей — <w-iframe>, <w-artifact> и содержимое html.inject — строится из уже слитой конфигурации страницы и наследует тему рекурсивно. Поэтому страница (или модуль, поставляющий несколько таких страниц) оформляет всё, что под ней, а не только саму себя.

Переменные --wippy-host-*

Хост предоставляет набор CSS-переменных --wippy-host-* для настройки элементов оболочки Web Host — боковой панели, пузырей чата, строки ввода, разделителей панелей — не затрагивая стили дочерних iframe. Переопределяйте их через customCSS или cssVariables в области :root (переменные уже имеют префикс и не утекают в дочерние iframe):

theming: {
  host: {
    customCSS: `
    :root {
      --wippy-host-sidebar-width-open: 20rem;
      --wippy-host-splitter-color: transparent;
      --wippy-host-message-radius: 0.5rem;
      --wippy-host-message-user-bg: var(--p-info-100);
      --wippy-host-message-agent-bg: var(--p-warn-100);
    }
    /* Селекторы классов должны быть ограничены .wippy-host-app */
    .wippy-host-app .chat-message__footer { display: none; }
  `
  }
}

Переменные вёрстки

Переменная По умолчанию Описание
--wippy-host-sidebar-width-open 16rem Ширина боковой панели в развёрнутом состоянии
--wippy-host-sidebar-width-closed 3.5rem Ширина боковой панели в свёрнутом состоянии
--wippy-host-splitter-width 1px Толщина линии разделителя панелей
--wippy-host-splitter-hit-area 10px Область захвата разделителя панелей
--wippy-host-splitter-color surface-200/600 Цвет разделителя панелей
--wippy-host-chat-bg surface-50/700 Фон контейнера чата
--wippy-host-chat-padding-x 10px Горизонтальные отступы списка сообщений
--wippy-host-meta-bar-border-color surface-200/600 Граница строки агента/модели

Переменные сообщений

Переменная По умолчанию Описание
--wippy-host-message-bg surface-50/700 Фон сообщения по умолчанию
--wippy-host-message-border-color surface-200/600 Граница пузыря сообщения
--wippy-host-message-shadow 0 1px 2px 0 rgba(...) Тень пузыря сообщения
--wippy-host-message-font-size 0.875rem Размер текста тела сообщения
--wippy-host-message-radius 1rem Скругление углов пузыря сообщения
--wippy-host-message-padding-x 1rem Горизонтальные отступы сообщения
--wippy-host-message-padding-y 0.5rem Вертикальные отступы сообщения
--wippy-host-message-gap 0.5rem Промежуток между аватаром и пузырём
--wippy-host-message-spacing 1rem Вертикальный интервал между сообщениями
--wippy-host-message-user-bg primary-50 Фон сообщения пользователя
--wippy-host-message-agent-bg yellow-50/surface-800 Фон сообщения агента
--wippy-host-tool-bg help-50 Фон вызова инструмента
--wippy-host-tool-border help-300 Левая граница вызова инструмента
--wippy-host-avatar-size 2rem Диаметр аватара в сообщении

Переменные ввода

Переменная По умолчанию Описание
--wippy-host-input-bg surface-50/700 Фон строки ввода
--wippy-host-input-border-color surface-200/600 Верхняя граница строки ввода
--wippy-host-input-group-bg surface-0/800 Фон поля ввода
--wippy-host-input-group-border-color surface-300/700 Граница поля ввода
--wippy-host-input-group-radius 0.375rem Скругление углов поля ввода
--wippy-host-input-min-height 2.5rem Начальная высота textarea
--wippy-host-input-max-height 10rem Максимальная высота textarea

Переменные подсказок

Переменная По умолчанию Описание
--wippy-host-prompt-bg surface-100/800 Фон подсказки-предложения
--wippy-host-prompt-border-color surface-300/600 Граница подсказки-предложения
--wippy-host-prompt-radius 0.5rem Скругление углов подсказки-предложения

Эти переменные влияют только на оболочку хоста. Стили дочерних iframe не затрагиваются — они получают только стандартный конвейер инъекции, описанный выше.

Смотрите также

  • Оформление — справочник CSS-токенов, сопоставление с Tailwind и шаблоны стилей веб-компонентов
  • Прокси и изоляция — как работает конвейер инъекции прокси и чем ProxyConfig управляет на уровне протокола
  • Движки рендеринга — CSS хоста доходит и до srcdoc-iframe, и до shadow root Web Fragment