Configurator Styling
Customize the OV25 configurator UI with Shadow DOM, CSS variables, data attributes, and class names.
This document explains how to customize the OV25 configurator UI: Shadow DOM and why styles must pass through inject, display modes, global CSS variables, data attributes, class names, and the ov: Tailwind prefix.
1. Overview: Shadow DOM and Why Inject Is Needed
Many configurator components render inside Shadow DOM. Shadow roots do not inherit styles from the host document, so custom styles must be passed via branding.cssString in the inject config. Without this, your CSS will not reach the configurator UI.
Components by Shadow DOM Usage
| Component | Shadow DOM? | Notes |
|---|---|---|
| Gallery, Price, Name | No | Render in document; inherit document styles |
| Variants, Swatches, Configure button, Carousel | Yes | Use Shadow DOM; require branding.cssString |
Source: src/utils/inject.tsx – shouldCreateShadowDOM returns false only for gallery, price, name.
Global Shadow Containers
Created by inject, each receives [sharedStylesheet, cssVariablesStylesheet(cssString)]:
ov25-mobile-drawer-containerov25-configurator-view-controls-containerov25-popover-portal-containerov25-toaster-containerov25-swatchbook-portal-container
2. Passing Custom Styles
Use branding.cssString in your inject config:
How branding.cssString Is Applied
- Shadow DOM:
createCSSVariablesStylesheet(cssString)is appended to each shadow root'sadoptedStyleSheets. - Document:
setupCSSVariables(cssString)adds the same stylesheet todocument.adoptedStyleSheetsfor light-DOM components (gallery, price, name).
Reference: dev/react-test/tests/single-custom-css.jsx.
3. Display Modes and Their Styling Hooks
Variant Display Modes
| Mode | Data Attribute | CSS Variables |
|---|---|---|
| Wizard | data-ov25-wizard-variants-mode="inline" | "drawer" | --ov25-wizard-variants-content-height, --ov25-wizard-variants-filter-height |
| List | data-ov25-list-variants-mode="inline" | Uses --ov25-wizard-variants-content-height |
| Tabs | data-ov25-tabs, data-ov25-tab, data-ov25-tab-id, data-ov25-tab-active | — |
| Tree | data-ov25-tree-variants-mode={mode} | — |
| Accordion | data-ov25-accordion-variants-mode={mode} | — |
Inline vs Sheet/Drawer
data-ov25-inline-liston#ov25-aside-menuwhen variants are inline.- Variables:
--ov25-inline-list-aside-min-height,--ov25-inline-list-aside-max-height-mobile.
Snap2 Variants Panel
data-ov25-variants-panel,data-open="true"for the slide panel.- Styled in
globals.css.
4. Global CSS Variables Reference
Override these in :root or via branding.cssString to theme the configurator.
Color Variables
| Variable | Default | Purpose |
|---|---|---|
--ov25-background-color | #ffffff | Main background |
--ov25-secondary-background-color | #f6f6f6 | Secondary background |
--ov25-text-color | black | Primary text |
--ov25-secondary-text-color | #000000 | Secondary text |
--ov25-primary-color | rgb(65, 65, 65) | Buttons, accents |
--ov25-border-color | #E5E5E5 | Borders |
--ov25-border-color-secondary | #282828 | Dark borders |
--ov25-hover-color | oklch(...) | Hover states |
--ov25-color-handle | #000000 | Drawer handle |
--ov25-cta-color | #22c55e | CTA buttons |
--ov25-cta-color-hover | #16a34a | CTA hover |
--ov25-cta-color-light | #4ade80 | CTA light |
--ov25-destructive | #ef4444 | Destructive actions |
--ov25-highlight-color | #00fbff | Highlights |
Layout and Sizing
| Variable | Purpose |
|---|---|
--ov25-rounded, --ov25-rounded-xs … --ov25-rounded-full | Border radius scale |
--ov25-button-border-radius, --ov25-button-border-width | Button styling |
--ov25-gallery-gap | Gap between gallery and carousel |
--ov25-configurator-iframe-background-color, --ov25-configurator-iframe-border-radius | Iframe styling |
--ov25-variant-thumb-border-radius | Variant thumbnails |
Typography
| Variable | Purpose |
|---|---|
--ov25-text-xs-size … --ov25-text-xl-size | Font sizes |
--ov25-text-xs-line-height … --ov25-text-xl-line-height | Line heights |
--ov25-360-font-family | 360° label font |
Display-Mode-Specific
| Variable | Used By |
|---|---|
--ov25-wizard-variants-content-height | Wizard/list inline |
--ov25-wizard-variants-filter-height | Wizard filter bar |
--ov25-inline-list-aside-min-height | Inline list aside |
--ov25-inline-list-aside-min-height-mobile, --ov25-inline-list-aside-max-height-mobile | Mobile inline list |
View Controls and Overlays
| Variable | Purpose |
|---|---|
--ov25-configurator-view-controls-text-color | Overlay controls text |
--ov25-overlay-button-color | Overlay button background |
--ov25-configurator-variant-drawer-handle-color | Drawer handle |
Swatch Flash Animations
| Variable | Default | Purpose |
|---|---|---|
--ov25-swatch-flash-duration | 0.5s | Duration for swatch icon and count flash animations |
Note: --ov25-text-md-size is referenced in #ov25-mobile-savings-amount but not defined in :root; use an existing variable or add it.
5. Class Names and Data Attributes for Targeting
Use these selectors in branding.cssString to target specific UI elements.
Stable Class Names
| Class | Component | Purpose |
|---|---|---|
.ov25-variant-control | ProductOptions | Option wrapper |
.ov25-variant-name | DefaultVariantCard | Variant name |
.ov25-variant-thumb-wrapper | VariantThumb | Thumbnail wrapper |
.ov25-variant-thumb-overlay | VariantThumb | Overlay |
.ov25-variant-card-gradient | VariantThumb | Variant card overlay gradient |
.ov25-variant-image-container | VariantThumb | Image container |
.ov25-selection-thumbnail | Selection thumbnails | Fabric icons, etc. |
.ov25-carousel-tab | Tabs | Tab styling |
.ov25-group-name | Group labels | Group name |
.ov25-swatch-icon | Swatch icons | SVG styling |
.ov25-gradient | Tabs, VariantThumb, OVOrBrandLogo | Gradient; hardcoded, no variable |
.radial_gradient | VariantThumb | Radial gradient overlay on variant cards |
.shadow-inner-intense | VariantThumb | Inner shadow on variant cards |
.ov25-dimensions-width, .ov25-dimensions-height, .ov25-dimensions-depth, .ov25-dimensions-mini | Iframe dimensions | 3D viewer dimensions (styled via cssString sent to iframe) |
.ov25-thumbnail-scroll | Carousel | Hides scrollbar |
.ov25-controls-text | — | Hidden by default |
.ov25-swatch-flash-destructive, .ov25-swatch-flash-cta | FilterControls | Swatch icon flash animations |
.ov25-swatch-count-flash-destructive, .ov25-swatch-count-flash-cta | FilterControls | Swatch count text flash animations |
6. SwatchBook
SwatchBook has its own set of IDs and classes for customization.
| ID / Class | Purpose |
|---|---|
#ov25-selected-swatches-container | Swatches summary trigger (click opens SwatchBook) |
#ov25-swatchbook | Swatch book dialog |
#ov25-swatchbook-title | Dialog title |
#ov25-swatchbook-featured | Featured/zoomed swatch area |
#ov25-swatchbook-content | Main content area |
#ov25-swatchbook-empty | Empty state container |
#ov25-swatchbook-swatches-list | Swatch grid |
#ov25-swatchbook-controls | Footer controls |
#ov25-swatchbook-add-to-cart-button | Add-to-cart button wrapper |
#ov25-swatchbook-add-button | Add button |
.ov25-selected-swatch-image-container | Featured swatch image wrapper |
.ov25-selected-swatch-name, .ov25-selected-swatch-option, .ov25-selected-swatch-sku, .ov25-selected-swatch-description | Featured swatch text |
.ov25-swatch-item | Single swatch card |
.ov25-swatch-image-container | Swatch image wrapper |
.ov25-swatch-image | Swatch image |
.ov25-swatch-zoom-button | Zoom overlay on swatch |
.ov25-swatch-zoom-in-icon, .ov25-swatch-zoom-out-icon | Zoom icons (.group:hover increases opacity) |
.ov25-empty-swatch-square | Empty slot placeholder |
.ov25-swatchbook-empty-title, .ov25-swatchbook-empty-description | Empty state text |
7. Data Attributes
| Attribute | Values | Purpose |
|---|---|---|
data-ov25-wizard-variants-mode | inline, drawer | Wizard layout |
data-ov25-list-variants-mode | inline | List layout |
data-ov25-tree-variants-mode | — | Tree layout |
data-ov25-accordion-variants-mode | — | Accordion layout |
data-ov25-inline-list | (present) | Inline list on aside |
data-ov25-variants-panel | — | Snap2 variants panel |
data-ov25-option-id | option ID | Option container |
data-ov25-variant-option | option ID | Variant option |
data-ov25-tabs, data-ov25-tab, data-ov25-tab-id, data-ov25-tab-active | — | Tabs |
data-ov25-tabs-container | — | Tabs wrapper |
data-ov25-tabs-dropdown | — | Dropdown tab mode |
data-ov25-tab-select | — | Tab select element |
data-ov25-swatch-book-button, data-ov25-swatch-book-count | — | Swatch book |
data-ov25-configure-button | — | Configure button |
data-open | "true" | Snap2 variants panel open state |
data-stacked | "true" | Iframe container stacked carousel layout |
8. IDs
| ID | Purpose |
|---|---|
#ov25-aside-menu | Aside container |
#ov25-controls | Variants container |
#ov25-configurator-variant-menu-container | Variant menu |
#ov25-variants-header | Variants header (hardcoded background: #0c5358) |
#ov25-variants-header-mobile | Mobile variants header |
#ov25-variant-group-content | Variant group content |
#ov25-option-selector-tabs | Tabs container |
#ov25-price-container | Price container |
#ov25-product-carousel | Carousel |
#ov25-drawer-toggle-button | Mobile drawer toggle |
#ov25-drawer-content | Drawer content |
#ov25-provider-root | React root |
#ov25-configurator-iframe-container | Iframe container |
#ov25-mobile-price-container | Mobile price wrapper |
#ov25-mobile-savings-amount | Mobile savings text |
#ov25-mobile-subtotal | Mobile subtotal |
#ov25-mobile-price | Mobile price |
#true-ov25-configurator-iframe-container | Replaced gallery container (carousel sibling) |
#true-carousel | Carousel wrapper when stacked |
9. Tailwind Prefix (ov:)
All Tailwind utilities use the ov: prefix (e.g. ov:flex, ov:p-2). This avoids clashes with host page Tailwind. Custom styles should not rely on unprefixed Tailwind classes from the configurator.
10. Iframe Dimensions Styling
The dimensions overlay (width, height, depth) is rendered inside the 3D iframe. cssString is sent via VIEW_DIMENSIONS and VIEW_MINI_DIMENSIONS messages. Target these classes in your branding.cssString:
.ov25-dimensions-width.ov25-dimensions-height.ov25-dimensions-depth.ov25-dimensions-mini
Example: dev/react-test/tests/single-custom-css.jsx.
11. Replaced Elements
When replace: true on a selector, the host element gets ov25-configurator-{componentName} (e.g. ov25-configurator-gallery, ov25-configurator-variants). Use these to target replaced containers from outside Shadow DOM.
12. Hardcoded Values
These are not driven by CSS variables; override with !important or higher specificity if needed:
#ov25-variants-header:background: #0c5358.ov25-gradient:linear-gradient(90deg, #26E8FE 0%, #808AFF 50%, #A41EFE 100%)