Preparing the latest guides, releases, and feature request updates.
Loading guides
Preparing the right Knowledge Base content for this platform.
Custom CSS for the product customizer | Chamevo Support Center
Custom CSS for the product customizer
How to style the Chamevo product customizer using CSS custom properties and the ::part() pseudo-element.
Updated April 29, 20265 min read
Chamevo's product customizer is a Stencil web component (<cv-customizer>) that uses Shadow DOM. Shadow DOM encapsulates component styles, so regular CSS selectors cannot reach inside it. The old fpd- class selectors used in earlier versions no longer work.
There are two supported ways to style the customizer from your theme or stylesheet:
CSS custom properties (--cv-*) β override theme tokens that cascade through the shadow boundary.
::part() pseudo-element β target named shadow DOM parts exposed by the component.
Where to add custom CSS
Option 1: WordPress Customizer
Go to Appearance β Customize β Additional CSS. This stylesheet loads after plugin styles and affects the full page.
Option 2: Child theme stylesheet
Add rules to your child theme's style.css.
Option 3: UI Composer β Custom CSS field
In Chamevo β UI Composer, open a layout and add CSS in the Custom CSS field. This CSS is injected into <head> on pages using that layout, and is the most targeted option when different products need different styles.
All three locations support CSS custom properties and ::part() selectors.
CSS custom properties
CSS custom properties cascade through the shadow DOM boundary. Override them on cv-customizer (or any ancestor element) to change the customizer's colors, spacing, and layout without ::part().
Accent color β buttons, active states, focus rings
--cv-secondary
#8b8d98
Secondary text and icons
--cv-bg
#fcfcfd
Main panel and module background
--cv-bg-secondary
#f8f8f8
List hover states, secondary surfaces
--cv-bg-tertiary
#f0f0f3
Chip backgrounds, tertiary surfaces
--cv-canvas-bg
#ffffff
Canvas area background
--cv-text
#1c2024
Primary text
--cv-text-secondary
#60646c
Labels, placeholders, meta text
--cv-on-primary
#ffffff
Text on primary-colored elements
--cv-border
#d9d9e0
Dividers and non-interactive borders
--cv-border-interactive
#cdced6
Input, button, and card borders
--cv-border-hover
#b9bbc6
Hovered border color
--cv-success
#30a46c
Success indicators
--cv-error
#e5484d
Error indicators
--cv-warning
#ffc53d
Warning indicators
Border radius tokens
Property
Default
Purpose
--cv-radius-sm
0.25rem
Small elements (chips, tags)
--cv-radius
0.375rem
Default radius (inputs, cards)
--cv-radius-lg
0.5rem
Larger elements (panels, dropdowns)
Layout tokens
Property
Default
Purpose
--cv-mainbar-width
70px
Width of the vertical module navigation bar
--cv-sidebar-width
280px
Width of the module content panel (sidebar mode)
--cv-panel-width
260px
Module panel width (dialog/overlay mode)
--cv-toolbar-height
48px
Element editing toolbar height
--cv-actions-bar-height
40px
Actions bar height
Customizer dimensions
Set the customizer height in the UI Composer, not in CSS. Go to Chamevo β UI Composer, open an interface, and use Layout β Dimensions. You get Height, Min Height, and Max Height fields per device β Desktop, Tablet, and Mobile β each with a unit picker (px, %, vh, vw, rem). Chamevo generates the CSS below for you, correctly scoped and correctly ordered. See configure the UI Composer for custom layouts.
Reach for CSS only when you need something the three fields cannot express β a height driven by a container query, a calc() expression, or a breakpoint other than tablet and mobile.
Property
Default
Purpose
--cv-customizer-height
700px
Target height of the customizer container
--cv-customizer-min-height
500px
Smallest height the customizer can shrink to
--cv-customizer-max-height
70vh
Largest height the customizer can grow to
--cv-customizer-bg
var(--cv-bg-secondary) (#f8f8f8)
Customizer container background (behind the canvas and panels)
The three height tokens work together. The rendered height equals --cv-customizer-height, but --cv-customizer-min-height floors it and --cv-customizer-max-height caps it. Both limits beat the height you set, so raising --cv-customizer-height alone does nothing once it passes the cap β raise the cap too. The same applies downward: lower the floor before shrinking the height below it.
With the defaults, the customizer aims for 700px but caps at 70vh on shorter screens, so it always fits the viewport. This cap is the most common reason a height override appears to be ignored.
Set the dimension tokens on cv-customizer::part(base), not on cv-customizer. The height tokens are read by the customizer's root layout container β the base part β and the small-screen layout re-declares them directly on that container, so overrides on the cv-customizer element can be ignored. Overrides on ::part(base) always win. The UI Composer emits its rules against the same selector.
/* Lock the customizer to exactly 800px tall */
cv-customizer::part(base) {
--cv-customizer-height: 800px;
--cv-customizer-min-height: 800px;
--cv-customizer-max-height: 800px;
}
On small screens (mobile), the customizer switches to a fluid layout where --cv-customizer-min-height becomes 90vh and --cv-customizer-max-height becomes 100vh. The UI Composer's Dimensions fields cover per-device heights without writing any of this. To do it by hand, use the same breakpoints Chamevo generates β 1024px for tablet and 768px for mobile, widest rule first:
Each token cascades independently. A device that leaves Min Height empty in the UI Composer inherits the next wider device's value for that one token, not the whole set.
Your CSS wins over the UI Composer. Chamevo emits the generated Dimensions rules before the interface's Custom CSS, so hand-authored overrides at the same specificity take precedence. You do not need !important to override a value set in the Dimensions fields.
Scrollbar tokens
Property
Default
Purpose
--cv-scrollbar-thumb
rgb(0 0 0 / 0.2)
Scrollbar thumb color
--cv-scrollbar-track
transparent
Scrollbar track color
--cv-scrollbar-size
6px
Scrollbar width
Override example
/* Change the accent color and widen the module sidebar */
cv-customizer {
--cv-primary: #e11d48;
--cv-sidebar-width: 320px;
}
Pre-built style classes
Apply these classes to <cv-customizer> or any ancestor to activate built-in style presets.
Class
Effect
cv-dark
Dark color scheme β overrides all surface, text, and border tokens
cv-style-rounded
Larger radii (--cv-radius: 0.75rem) and softer shadows
cv-style-sharp
Zero radii and minimal shadows
To apply a class from PHP (for example, always dark mode):
/* All customizers on the site use the rounded style */
cv-customizer {
--cv-radius: 0.75rem;
--cv-radius-sm: 0.5rem;
--cv-radius-lg: 1rem;
}
::part() selectors
::part() lets you style specific elements inside the shadow DOM from an external stylesheet. All parts below are exposed on cv-customizer β either defined directly or re-exported from child components.
Layout parts
Selector
Target
cv-customizer::part(base)
Root container div
cv-customizer::part(main)
Main layout area (contains nav, canvas, panel)
cv-customizer::part(canvas-area)
Canvas wrapper region
cv-customizer::part(canvas-scroll)
Scrollable canvas container
cv-customizer::part(canvas-sizer)
Canvas sizing div
cv-customizer::part(canvas)
The FabricJS canvas element wrapper
cv-customizer::part(canvas-lock-overlay)
Overlay shown when canvas is locked
Navigation bar (module nav)
Selector
Target
cv-customizer::part(mainbar)
The module navigation bar (vertical or horizontal)
cv-customizer::part(mainbar-item)
Individual module nav button
cv-customizer::part(mainbar-vertical)
Navigation bar when in vertical (side) orientation
cv-customizer::part(mainbar-horizontal)
Navigation bar when in horizontal (bottom) orientation
Module panel
Selector
Target
cv-customizer::part(module-panel)
The module content panel
cv-customizer::part(module-header)
Module panel header bar
cv-customizer::part(module-content)
Module panel scrollable content area
Actions bar
Selector
Target
cv-customizer::part(actions-bar)
Any actions bar instance
cv-customizer::part(actions-bar-top)
Top actions bar
cv-customizer::part(actions-bar-bottom)
Bottom actions bar
Element editing toolbar
The toolbar appears when an element is selected on the canvas. The top-level tools (Edit, Color, Font, Size, Format, Effect, Filters, Transform, Position) are rendered into toolbar-nav. The Color tool reveals a second row of sub-tabs (Fill, Patterns, Stroke, Shadow), each individually targetable. The Color tool's Fill sub-tab also shows an opacity slider, which is exposed as its own part.
Selector
Target
cv-customizer::part(toolbar)
The element editing toolbar
cv-customizer::part(toolbar-nav)
Toolbar navigation tab strip
cv-customizer::part(toolbar-body)
Toolbar content area
cv-customizer::part(toolbar-subtabs)
Color sub-tab strip (Fill / Patterns / Stroke / Shadow)
cv-customizer::part(toolbar-subtab)
Any color sub-tab pill
cv-customizer::part(toolbar-subtab-fill)
Fill sub-tab
cv-customizer::part(toolbar-subtab-patterns)
Patterns sub-tab
cv-customizer::part(toolbar-subtab-stroke)
Stroke sub-tab
cv-customizer::part(toolbar-subtab-shadow)
Shadow sub-tab
cv-customizer::part(opacity)
Opacity slider (shown under the Color tool's Fill sub-tab)
Image module (Upload / Pixabay / AI / QR Code)
The Image module renders a tab strip with up to four tabs depending on configuration: Upload, Pixabay, Text-to-Image (AI), and QR Code. Each tab is exposed as its own part.
Match all three height tokens so the customizer ignores the viewport. In the UI Composer, enter the same value in Height, Min Height, and Max Height for each device.
Useful when you want elements selectable but not editable on the frontend:
cv-customizer::part(toolbar) {
display: none;
}
Hide a specific module button in the navigation bar
Individual module navigation buttons share the same mainbar-item part, so ::part() alone cannot target one specific module. Use the position-based selector :nth-child() as a CSS fallback:
/* Hide the third module button in the navigation bar */
cv-customizer::part(mainbar-item):nth-child(3) {
display: none;
}
The order matches the mainBarModules array in your Chamevo configuration. Because this is position-based, it breaks if you reorder modules. The reliable way to remove modules is to omit them from mainBarModules in your chamevo_app_options filter:
You cannot select inside a part.::part(mainbar-item) span does not work. You can only style the part element itself.
You cannot target by inner attribute. Individual modules, actions, and tools use data-module, data-action, and data-tool attributes inside the shadow DOM. These are not reachable from external CSS. For per-item targeting, remove the item from configuration instead (e.g. mainBarModules, actions).
You can chain pseudo-classes and the part's own attributes.::part(toolbar-subtab):hover and ::part(toolbar-subtab)[aria-selected="true"] both work.
Custom properties set in a ::part() rule reach only that part and its children β not the whole shadow tree. Set theme tokens (colors, radii, widths) on cv-customizer so every component receives them. The customizer dimension tokens are the exception: set them on ::part(base), the element that reads them.
Apply dark mode to specific pages
/* Only on pages with the class 'my-dark-page' */
.my-dark-page cv-customizer {
--cv-bg: #111113;
--cv-bg-secondary: #18191b;
--cv-bg-tertiary: #212225;
--cv-canvas-bg: #1b1b1f;
--cv-text: #edeef0;
--cv-text-secondary: #b0b4ba;
--cv-border: #363a3f;
--cv-border-interactive: #43484e;
}
Or use the built-in class:
.my-dark-page cv-customizer {
/* Activates the built-in dark preset */
}
/* Apply cv-dark class conditionally */
add_filter('chamevo_app_options', function($options) {
if (/* your condition */) {
$options['customizerClass'] = 'cv-dark';
}
return $options;
});
FAQ
Q: The old .fpd- class selectors stopped working after I updated. Why?
A: Chamevo v2 replaced the legacy fpd-js rendering engine with chamevo-js, which uses Stencil web components and Shadow DOM. Shadow DOM encapsulates styles, so fpd- class selectors no longer reach the customizer's internals. Use --cv-* custom properties or ::part() selectors instead.
Q: Can I override --cv-* properties inside a ::part() rule?
A: Yes, but they reach only that part and its children β not the whole shadow tree. Set theme tokens on cv-customizer or an ancestor so they cascade everywhere. The dimension tokens are the exception: set them on cv-customizer::part(base), the element that reads them.
Q: Do ::part() selectors work in all browsers?
A: Yes. ::part() is supported in all modern browsers (Chrome, Firefox, Safari, Edge). It is not supported in Internet Explorer, which Chamevo does not support.
Q: Can I use JavaScript to add CSS classes to <cv-customizer>?
A: Yes. document.querySelector('cv-customizer').classList.add('cv-dark') works and will apply the corresponding CSS tokens.
Q: How do I hide a specific tab inside the Image module?
A: Each image source has its own ::part(). Hide the QR Code tab with cv-customizer::part(images-tab-qrcode) { display: none; }, the Pixabay tab with images-tab-pixabay, the AI tab with images-tab-text2img, or the upload tab with images-tab-upload.
Q: How do I hide the Shadow tab on the color toolbar?
A: Use cv-customizer::part(toolbar-subtab-shadow) { display: none; }. The same pattern works for toolbar-subtab-fill, toolbar-subtab-patterns, and toolbar-subtab-stroke.
Q: How do I stop customers from changing element opacity?
A: Hide the opacity slider with cv-customizer::part(opacity) { display: none; }. It appears under the Color tool's Fill sub-tab when an element is selected.
Q: Can I hide a single module from the navigation bar with CSS?
A: Only by position with :nth-child() β ::part(mainbar-item) targets every module button uniformly. For a reliable, language-independent way to remove modules, set mainBarModules through the chamevo_app_options filter and omit the modules you do not want.
Q: How do I change the height of the product customizer?
A: Use Chamevo β UI Composer β Layout β Dimensions. Set Height, Min Height, and Max Height per device, no CSS required. In CSS, override --cv-customizer-height on cv-customizer::part(base), alongside --cv-customizer-min-height (default 500px) and --cv-customizer-max-height (default 70vh). To set an exact height, match all three to the same value.
Q: The customizer is shorter than the height I set. Why?
A: --cv-customizer-max-height caps it, and defaults to 70vh. On shorter screens that limit wins over --cv-customizer-height. Raise Max Height in the UI Composer, or set --cv-customizer-max-height higher on cv-customizer::part(base). Also check that your height overrides target ::part(base) β dimension tokens set on cv-customizer itself can be ignored.
Q: My CSS height is being overridden by the UI Composer. How do I win?
A: You already do. Chamevo emits the generated Dimensions rules before the interface's Custom CSS, so your rule wins at equal specificity. If it still does not apply, check that it targets cv-customizer::part(base) and that you edited the interface the product actually uses.