logo

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

ComponentShadow DOM?Notes
GalleryNoRenders in document; inherits document styles
Price, NameYesMount in light DOM, but their content renders inside an Ov25ShadowHost shadow root (ov25-configurator-price-container / ov25-configurator-name-container); style via branding.cssString
Variants, Swatches, Configure button, CarouselYesUse Shadow DOM; require branding.cssString

Source: src/utils/inject.tsxshouldCreateShadowDOM returns false only for gallery, price, name (the Price and Name components then wrap their own content in Ov25ShadowHost).

Global Shadow Containers

Created by inject, each receives [sharedStylesheet, userCustomCssStylesheet(cssString)]:

  • ov25-mobile-drawer-container
  • ov25-snap2-checkout-sheet-container
  • ov25-configurator-view-controls-container
  • ov25-popover-portal-container
  • ov25-modal-portal-container
  • ov25-toaster-container
  • ov25-swatchbook-portal-container

2. Passing Custom Styles

Use branding.cssString in your inject config:

branding: {
  cssString: `
    .ov25-variant-control { background-color: red; }
    #ov25-variants-header { background: #1a1a1a !important; }
  `,
},

How branding.cssString Is Applied

  • Shadow DOM: createuserCustomCssStylesheet(cssString) is appended to each shadow root's adoptedStyleSheets (global containers and every Ov25ShadowHost, including price and name).
  • Document: there is no document-level stylesheet adoption - the gallery renders in light DOM and inherits the host page's styles directly.

Reference: dev/react-test/tests/single-custom-css.jsx.


3. Display Modes and Their Styling Hooks

Variant Display Modes

ModeData AttributeCSS Variables
Wizarddata-ov25-wizard-variants-mode="inline" | "drawer"--ov25-wizard-variants-content-height, --ov25-wizard-variants-filter-height
Listdata-ov25-list-variants-mode="inline"Uses --ov25-wizard-variants-content-height
Tabsdata-ov25-tabs, data-ov25-tab, data-ov25-tab-id, data-ov25-tab-active-
Treedata-ov25-tree-variants-mode={mode}-
Accordiondata-ov25-accordion-variants-mode="inline" | "drawer"-

Inline vs Sheet/Drawer

  • data-ov25-inline-list on #ov25-aside-menu when variants are inline.
  • Variables: --ov25-inline-list-aside-min-height, --ov25-inline-list-aside-max-height-mobile.

Inline (sticky)

The inline-sticky display mode keeps the standard or bed-configurator gallery visible while the page-level variant list scrolls.

  • The active gallery host has data-ov25-inline-sticky-active="true".
  • data-ov25-inline-sticky-mobile identifies whether the mobile sticky layout is active.
  • The runtime measures fixed/sticky storefront headers and exposes its resolved geometry through --ov25-sticky-* custom properties on the gallery and variants hosts.
  • On mobile, the viewer is full width and the carousel is moved to the configured mobile target. The automatic mobile fallback target is [data-ov25-sticky-mobile-carousel].
  • A carousel moved outside the gallery is marked with data-ov25-external-carousel.

Use the Shopify or WooCommerce Header Selector setting only when automatic header detection does not identify the correct storefront header. Desktop and mobile carousel targets are configured separately by those integrations.

Snap2 Variants Panel

  • data-ov25-variants-panel, data-open="true" for the slide panel.
  • Styled in globals.css.
  • Snap2 supports Dialog and Inline on desktop, and Dialog, Drawer, and Inline on mobile.
  • In the desktop Dialog layout, variant position controls the side of the main variant panel. Module position controls whether compatible modules use the left side, right side, or bottom module panel.

4. Global CSS Variables Reference

Override these in :root or via branding.cssString to theme the configurator.

Color Variables

VariableDefaultPurpose
--ov25-background-color#ffffffMain background
--ov25-secondary-background-color#f6f6f6Secondary background
--ov25-text-colorblackPrimary text
--ov25-secondary-text-color#000000Secondary text
--ov25-primary-color#ffffffButtons, accents
--ov25-border-color#E5E5E5Borders
--ov25-border-color-secondary#282828Dark borders
--ov25-hover-coloroklch(...)Hover states
--ov25-cta-color#22c55eCTA buttons
--ov25-cta-color-hover#16a34aCTA hover
--ov25-cta-color-light#4ade80CTA light
--ov25-destructive#ef4444Destructive actions
--ov25-highlight-colorunset (#26E8FE fallback in filter pills)Filter pill highlights; also the solid selected-variant ring color when --ov25-variant-thumb-ring-mode: solid is set (default is the gradient ring)

Layout and Sizing

VariablePurpose
--ov25-rounded, --ov25-rounded-xs--ov25-rounded-fullBorder radius scale
--ov25-button-border-radius, --ov25-button-border-widthButton styling
--ov25-gallery-gapGap between gallery and carousel
--ov25-configurator-iframe-background-color, --ov25-configurator-iframe-border-radiusIframe styling
--ov25-variant-thumb-border-radiusVariant thumbnails

Typography

VariablePurpose
--ov25-text-xs-size--ov25-text-xl-sizeFont sizes
--ov25-text-xs-line-height--ov25-text-xl-line-heightLine heights
--ov25-360-font-family360° label font

Display-Mode-Specific

VariableUsed By
--ov25-wizard-variants-content-heightWizard/list inline
--ov25-wizard-variants-filter-heightWizard filter bar
--ov25-inline-list-aside-min-heightInline list aside
--ov25-inline-list-aside-min-height-mobile, --ov25-inline-list-aside-max-height-mobileMobile inline list

View Controls and Overlays

VariablePurpose
--ov25-configurator-view-controls-text-colorOverlay controls text
--ov25-overlay-button-colorOverlay button background

Swatch Flash Animations

VariableDefaultPurpose
--ov25-swatch-flash-duration0.5sDuration 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

ClassComponentPurpose
.ov25-variant-controlProductOptionsOption wrapper
.ov25-variant-nameDefaultVariantCardVariant name
.ov25-variant-thumb-wrapperVariantThumbThumbnail wrapper
.ov25-variant-thumb-overlayVariantThumbOverlay
.ov25-variant-card-gradientVariantThumbVariant card overlay gradient
.ov25-variant-image-containerVariantThumbImage container
.ov25-size-variant-card-gridSize variantsGrid containing size cards
.ov25-size-variant-card-nameSizeVariantCardSize/product name
.ov25-size-variant-card-dimensionsSizeVariantCardDimensions wrapper
.ov25-size-variant-card-dimension-rowSizeVariantCardDimension row
.ov25-size-variant-card-dimension-lineSizeVariantCardHorizontal dimension line
.ov25-size-variant-card-dimension-markerSizeVariantCardEnd marker
.ov25-size-variant-card-dimension-valueSizeVariantCardDimension text value
.ov25-selection-thumbnailSelection thumbnailsFabric icons, etc.
.ov25-gallery-image-buttonProduct carouselProduct-image thumbnail button
.ov25-carousel-tabTabsTab styling
.ov25-group-nameGroup labelsGroup name
.ov25-swatch-iconSwatch iconsSVG styling
.ov25-gradientTabs, VariantThumb, OVOrBrandLogoGradient; hardcoded, no variable
.radial_gradientVariantThumbRadial gradient overlay on variant cards
.shadow-inner-intenseVariantThumbInner shadow on variant cards
.ov25-dimensions-width, .ov25-dimensions-height, .ov25-dimensions-depth, .ov25-dimensions-miniIframe dimensions3D viewer dimensions (styled via cssString sent to iframe)
.ov25-thumbnail-scrollCarouselHides scrollbar
.ov25-controls-text-Hidden by default
.ov25-swatch-flash-destructive, .ov25-swatch-flash-ctaFilterControlsSwatch icon flash animations
.ov25-swatch-count-flash-destructive, .ov25-swatch-count-flash-ctaFilterControlsSwatch count text flash animations

Snap2 module cards also expose stable part selectors:

SelectorPurpose
[data-ov25-module-variant-card-part="name"]Module name mounted in the card
[data-ov25-module-variant-card-part="tooltip"]Desktop module-name tooltip
[data-ov25-module-variant-card-part="dimensions"]Module dimensions
[data-ov25-module-variant-detail-part="title"]Module detail-sheet title

The module name and tooltip remain mounted so custom CSS can switch their visibility. In the Snap2 initialise menu, the name is visible on mobile by default and the tooltip is used on desktop.


6. SwatchBook

SwatchBook has its own set of IDs and classes for customization.

ID / ClassPurpose
#ov25-selected-swatches-containerSwatches summary trigger (click opens SwatchBook)
#ov25-swatchbookSwatch book dialog
#ov25-swatchbook-titleDialog title
#ov25-swatchbook-featuredFeatured/zoomed swatch area
#ov25-swatchbook-contentMain content area
#ov25-swatchbook-emptyEmpty state container
#ov25-swatchbook-swatches-listSwatch grid
#ov25-swatchbook-controlsFooter controls
#ov25-swatchbook-add-to-cart-buttonAdd-to-cart button wrapper
#ov25-swatchbook-add-buttonAdd button
.ov25-selected-swatch-image-containerFeatured swatch image wrapper
.ov25-selected-swatch-name, .ov25-selected-swatch-option, .ov25-selected-swatch-sku, .ov25-selected-swatch-descriptionFeatured swatch text
.ov25-swatch-itemSingle swatch card
.ov25-swatch-image-containerSwatch image wrapper
.ov25-swatch-imageSwatch image
.ov25-swatch-zoom-buttonZoom overlay on swatch
.ov25-swatch-zoom-in-icon, .ov25-swatch-zoom-out-iconZoom icons (.group:hover increases opacity)
.ov25-empty-swatch-squareEmpty slot placeholder
.ov25-swatchbook-empty-title, .ov25-swatchbook-empty-descriptionEmpty state text

7. Data Attributes

AttributeValuesPurpose
data-ov25-wizard-variants-modeinline, drawerWizard layout
data-ov25-list-variants-modeinlineList 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-idoption IDOption container
data-ov25-variant-optionoption IDVariant 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
data-selected"true", "false"Selection state on variant cards, size cards, option tabs, Snap2 module cards/type tabs, dining choices, and product-carousel items
data-ov25-inline-sticky-active"true"Inline-sticky gallery host
data-ov25-inline-sticky-mobile"true", "false"Active inline-sticky viewport mode
data-ov25-external-carousel(present)Carousel currently mounted in an external desktop/mobile target

8. IDs

IDPurpose
#ov25-aside-menuAside container
#ov25-controlsVariants container
#ov25-configurator-variant-menu-containerVariant menu
#ov25-variants-headerVariants header (background uses --ov25-background-color)
#ov25-variants-header-mobileMobile variants header
#ov25-variant-group-contentVariant group content
#ov25-option-selector-tabsTabs container
#ov25-price-containerPrice container
#ov25-product-carouselCarousel
#ov25-drawer-toggle-buttonMobile drawer toggle
#ov25-drawer-contentDrawer content
#ov25-provider-rootReact root
#ov25-configurator-iframe-containerIframe container
#ov25-mobile-price-containerMobile price wrapper
#ov25-mobile-savings-amountMobile savings text
#ov25-mobile-subtotalMobile subtotal
#ov25-mobile-priceMobile price
#true-ov25-configurator-iframe-containerReplaced gallery container (carousel sibling)
#true-carouselCarousel 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-gradient: linear-gradient(90deg, #26E8FE 0%, #808AFF 50%, #A41EFE 100%)

13. Examples

Override CSS variables

branding: {
  cssString: `
    :root {
      --ov25-primary-color: #1a1a1a;
      --ov25-cta-color: #2563eb;
    }
  `,
},

Target variant controls

branding: {
  cssString: `
    .ov25-variant-control {
      background-color: #f5f5f5;
      border-radius: 8px;
    }
  `,
},

Style dimensions overlay (inside iframe)

branding: {
  cssString: `
    .ov25-dimensions-width, .ov25-dimensions-height, .ov25-dimensions-depth, .ov25-dimensions-mini {
      border: 2px dashed green;
      scale: 1.2;
    }
  `,
},

Customize SwatchBook

branding: {
  cssString: `
    #ov25-swatchbook { border-radius: 16px; }
    .ov25-swatch-item { border: 1px solid #e5e5e5; }
    .ov25-swatchbook-empty-title { font-size: 1.25rem; }
  `,
},

Override variants header

branding: {
  cssString: `
    #ov25-variants-header {
      background: #1a1a1a !important;
    }
  `,
},