Инъекция 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 rootview.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, и устанавливает универсальный мост наследования после платформенных умолчаний темы. Затем он устанавливает составленныйcustomCSSglobal + 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