← Back to documentation
Introduction
Custom CSS allows you to fully customize the appearance of your variant image swatches.
You can change colors, sizes, spacing, fonts, and more to match your store's design.
The swatches render inside your theme's DOM, and the custom CSS you write is injected directly into the swatch stylesheet.
This means you can override any default style using the CSS variables listed below, or target specific elements with class selectors.
Custom CSS applies to product-page swatches only. Product-card swatches (on collection and home pages) are styled with the visual controls on the Swatch style page's Product card tab and do not load custom CSS.
Getting started
All custom CSS should be wrapped in the :root, :host selector. Using both ensures compatibility whether the swatches render normally or inside a Shadow DOM (some themes use Shadow DOM for app blocks).
Try this example to create a clean, modern look:
:root, :host {
--rubik-swatch-image-border-radius: 50%;
--rubik-swatch-image-selected-border-color: #2563EB;
--rubik-swatch-image-border-color: #ddd;
--rubik-swatch-image-hover-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
--rubik-swatch-option-name-color: #111;
}
Want pill-style buttons with a dark selected state? Try this:
:root, :host {
--rubik-swatch-pill-border-radius: 20px;
--rubik-swatch-pill-selected-background: #111;
--rubik-swatch-pill-selected-color: #fff;
--rubik-swatch-pill-selected-border-color: #111;
--rubik-swatch-pill-padding: 10px 20px;
}
You can override any CSS variable listed below, or target specific elements for advanced customization.
CSS variables reference
Below is a complete reference of all CSS variables you can customize. Each variable controls a specific aspect of the swatch appearance.
The Default column shows the built-in storefront fallback, which applies only while nothing else sets the variable: values saved in the Swatch style editor override these built-ins, and your custom CSS overrides both.
Layout & spacing
| Variable |
Default |
Description |
--rubik-swatch-margin-top |
5px |
Top margin of the swatch container |
--rubik-swatch-margin-bottom |
5px |
Bottom margin of the swatch container |
--rubik-swatch-fieldset-margin-top |
10px |
Top margin between multiple option groups |
--rubik-swatch-gap |
8px |
Gap between individual swatches |
--rubik-swatch-margin |
0 |
Margin around the swatch items container |
--rubik-swatch-alignment |
flex-start |
Horizontal alignment: flex-start (left), center, flex-end (right) |
--rubik-swatch-text-align |
left |
Text alignment of the option label |
--rubik-swatch-transition-duration |
0.2s |
Duration of hover/transition animations |
Option labels
| Variable |
Default |
Description |
--rubik-swatch-option-font-size |
14px |
Font size of the option name (e.g., "Color: Blue") |
--rubik-swatch-option-name-color |
#333333 |
Text color of the option name |
--rubik-swatch-option-name-display |
flex |
Display mode of the option name container |
--rubik-swatch-option-margin-bottom |
8px |
Bottom margin of the option fieldset |
--rubik-swatch-option-name-label-display |
inline |
Display mode of the option name label (e.g., "Color") |
--rubik-swatch-option-colon-display |
inline |
Display mode of the colon separator |
--rubik-swatch-option-name-value-display |
inline |
Display mode of the selected value (e.g., "Blue") |
Image swatches
| Variable |
Default |
Description |
--rubik-swatch-image-size |
70px |
Width (and default height) of image swatches |
--rubik-swatch-image-height |
var(--rubik-swatch-image-size) |
Height of image swatches (defaults to width for square) |
--rubik-swatch-image-border-width |
1px |
Border width of image swatches |
--rubik-swatch-image-border-color |
#e5e5e5 |
Border color of image swatches |
--rubik-swatch-image-border-radius |
0 |
Border radius (use 50% for circles) |
--rubik-swatch-image-aspect-ratio |
auto |
Aspect ratio of image swatches |
--rubik-swatch-image-background-color |
#ffffff |
Background color behind the image |
--rubik-swatch-image-object-fit |
contain |
How image fits: contain, cover, fill |
--rubik-swatch-image-hover-shadow |
0 2px 8px rgba(0, 0, 0, 0.15) |
Box shadow on hover |
--rubik-swatch-image-hover-scale |
1.1 |
Scale factor on hover (1 = no zoom) |
--rubik-swatch-image-selected-border-color |
#333 |
Border color when selected |
--rubik-swatch-image-selected-border-width |
1px |
Border width when selected |
--rubik-swatch-image-selected-outline |
none |
Outline when selected (e.g., "2px solid #000") |
--rubik-swatch-image-selected-outline-offset |
0 |
Offset of the selection outline |
--rubik-swatch-image-unavailable-opacity |
1 |
Opacity of a sold out / unavailable image swatch (0-1) |
Pill / text swatches
| Variable |
Default |
Description |
--rubik-swatch-pill-padding |
8px 16px |
Inner padding of pill swatches |
--rubik-swatch-pill-border-width |
1px |
Border width |
--rubik-swatch-pill-border-color |
#e5e5e5 |
Border color |
--rubik-swatch-pill-border-radius |
0 |
Border radius (use 20px+ for rounded pills) |
--rubik-swatch-pill-background |
#fff |
Background color |
--rubik-swatch-pill-color |
#333 |
Text color |
--rubik-swatch-pill-font-size |
14px |
Font size |
--rubik-swatch-pill-min-width |
50px |
Minimum width of pill swatches |
--rubik-swatch-pill-hover-shadow |
0 2px 8px rgba(0, 0, 0, 0.15) |
Box shadow on hover |
--rubik-swatch-pill-selected-background |
#333 |
Background color when selected |
--rubik-swatch-pill-selected-color |
#fff |
Text color when selected |
--rubik-swatch-pill-selected-border-color |
#333 |
Border color when selected |
--rubik-swatch-pill-selected-border-width |
1px |
Border width when selected |
--rubik-swatch-pill-selected-outline |
none |
Outline when selected |
--rubik-swatch-pill-selected-outline-offset |
0 |
Offset of the selection outline |
--rubik-swatch-pill-unavailable-opacity |
0.9 |
Opacity of unavailable pill swatches |
Text labels below images
| Variable |
Default |
Description |
--rubik-swatch-label-display |
none |
Set to block to show text labels below image swatches |
--rubik-swatch-label-background |
#f5f5f5 |
Background color of the label |
--rubik-swatch-label-border-color |
#e5e5e5 |
Border color of the label |
--rubik-swatch-label-color |
#333 |
Text color of the label |
--rubik-swatch-label-text-overflow |
ellipsis |
How overflowing text is handled |
--rubik-swatch-label-white-space |
nowrap |
Set to normal to allow wrapping |
--rubik-swatch-label-font-size |
11px |
Font size of the label |
--rubik-swatch-label-font-weight |
inherit |
Font weight of the label (the editor uses 600 for bold) |
--rubik-swatch-label-text-align |
center |
Text alignment inside the label |
--rubik-swatch-label-padding-block |
2px |
Vertical padding of the label |
--rubik-swatch-label-padding-inline |
4px |
Horizontal padding of the label |
--rubik-swatch-label-width |
var(--rubik-swatch-image-size) |
Width of the label; the editor sets 100% when labels are on, so the caption box below sizes it |
--rubik-swatch-label-flex-grow |
0 |
Set to 1 to stretch every label in a row to the same height (the editor does this when labels are on) |
--rubik-swatch-label-border |
1px solid #e5e5e5 |
Full border of the label; the editor sets none when labels are on, because the caption box draws the frame instead |
--rubik-swatch-label-border-top |
1px solid #e5e5e5 |
Top border of the label (between image and label) |
--rubik-swatch-label-border-bottom |
1px solid #e5e5e5 |
Bottom border of the label |
--rubik-swatch-caption-display |
contents |
The caption box around label and price. contents removes the box from layout; the editor sets flex when labels or prices are on |
--rubik-swatch-caption-border |
none |
Border of the caption box (left, right and bottom edges; the swatch above draws the top line) |
--rubik-swatch-caption-border-radius |
0 |
Bottom corner radius of the caption box |
--rubik-swatch-caption-background |
transparent |
Background of the caption box |
--rubik-swatch-caption-gap |
0 |
Space between the label and the price inside the caption box |
Sold out / unavailable
| Variable |
Default |
Description |
--rubik-swatch-unavailable-line-color |
#666 |
Color of the diagonal strike-through line (general) |
--rubik-swatch-image-unavailable-line-color |
#666 |
Strike-through line color for image swatches |
--rubik-swatch-pill-unavailable-line-color |
#666 |
Strike-through line color for pill swatches |
Prices under swatches
| Variable |
Default |
Description |
--rubik-swatch-price-display |
none |
Set to block to show each value's price under its swatch |
--rubik-swatch-price-font-size |
11px |
Font size of the price |
--rubik-swatch-price-font-weight |
inherit |
Font weight of the price (the editor uses 600 for bold) |
--rubik-swatch-price-color |
#333 |
Text color of the price |
--rubik-swatch-price-text-align |
center |
Text alignment of the price |
--rubik-swatch-price-padding-block |
2px |
Vertical padding of the price |
--rubik-swatch-price-plus-display |
inline |
The + after a price whose variants are not all the same price; none hides it |
--rubik-swatch-price-width |
var(--rubik-swatch-image-size) |
Width of the price box; the editor sets 100% when prices are on |
--rubik-swatch-price-border |
none |
Border of the price box, used only when text labels are off and the price frames itself |
--rubik-swatch-price-border-radius |
0 |
Corner radius of the price box, used only when text labels are off |
Carousel
| Variable |
Default |
Description |
--rubik-swatch-carousel-space |
0px |
Vertical padding inside the scrolling row, reserved so tooltips, hover zoom and selection rings are not clipped (the editor computes it) |
--rubik-swatch-carousel-space-inline |
0px |
Horizontal padding inside the scrolling row, reserved for the selection ring |
--rubik-swatch-carousel-nav-size |
28px |
Size of the desktop scroll arrows |
--rubik-swatch-carousel-nav-border-radius |
50% |
Roundness of the arrows |
--rubik-swatch-carousel-nav-background |
#fff |
Arrow background |
--rubik-swatch-carousel-nav-color |
#333 |
Arrow icon color |
--rubik-swatch-carousel-nav-border-color |
#e5e5e5 |
Arrow border color |
--rubik-swatch-carousel-nav-border-width |
1px |
Arrow border width |
--rubik-swatch-carousel-nav-shadow |
0 1px 4px rgba(0, 0, 0, 0.15) |
Arrow shadow |
--rubik-swatch-carousel-nav-mobile-display |
none |
Set to flex to show the arrows on touch screens too |
Dropdown - base
| Variable |
Default |
Description |
--rubik-swatch-dropdown-min-width |
150px |
Minimum width of the dropdown |
--rubik-swatch-dropdown-max-width |
100% |
Maximum width of the dropdown |
--rubik-swatch-dropdown-padding |
10px 40px 10px 16px |
Inner padding (right side larger for arrow) |
--rubik-swatch-dropdown-font-size |
14px |
Font size |
--rubik-swatch-dropdown-font-family |
inherit |
Font family (inherits from theme) |
--rubik-swatch-dropdown-line-height |
1.5 |
Line height |
--rubik-swatch-dropdown-color |
#333 |
Text color |
--rubik-swatch-dropdown-background |
#fff |
Background color |
--rubik-swatch-dropdown-arrow |
built-in chevron |
Custom arrow icon; supply your own url("data:image/svg+xml,...") to replace the default chevron |
--rubik-swatch-dropdown-border-width |
1px |
Border width |
--rubik-swatch-dropdown-border-color |
#e5e5e5 |
Border color |
--rubik-swatch-dropdown-border-radius |
0 |
Border radius |
--rubik-swatch-dropdown-transition |
0.2s |
Transition duration |
--rubik-swatch-dropdown-shadow |
none |
Box shadow |
Dropdown - hover
| Variable |
Default |
Description |
--rubik-swatch-dropdown-hover-border-color |
#ccc |
Border color on hover |
--rubik-swatch-dropdown-hover-shadow |
0 2px 8px rgba(0, 0, 0, 0.1) |
Box shadow on hover |
Dropdown - focus
| Variable |
Default |
Description |
--rubik-swatch-dropdown-focus-outline |
2px solid #333 |
Outline when focused |
--rubik-swatch-dropdown-focus-outline-offset |
2px |
Offset of the focus outline |
--rubik-swatch-dropdown-focus-border-color |
#333 |
Border color when focused |
--rubik-swatch-dropdown-focus-shadow |
0 0 0 3px rgba(0, 0, 0, 0.05) |
Box shadow when focused |
Dropdown - disabled
| Variable |
Default |
Description |
--rubik-swatch-dropdown-disabled-opacity |
0.6 |
Opacity when disabled |
--rubik-swatch-dropdown-disabled-background |
#f5f5f5 |
Background color when disabled |
Dropdown - options
| Variable |
Default |
Description |
--rubik-swatch-dropdown-option-padding |
8px |
Padding of dropdown options |
--rubik-swatch-dropdown-option-color |
inherit |
Text color of options |
--rubik-swatch-dropdown-option-background |
#fff |
Background color of options |
--rubik-swatch-dropdown-option-disabled-color |
#999 |
Text color of disabled options |
--rubik-swatch-dropdown-option-disabled-style |
italic |
Font style of disabled options |
--rubik-swatch-dropdown-option-selected-background |
#f0f0f0 |
Background color of the selected option |
--rubik-swatch-dropdown-option-selected-weight |
600 |
Font weight of the selected option |
Dropdown - mobile
| Variable |
Default |
Description |
--rubik-swatch-dropdown-mobile-padding |
12px 40px 12px 16px |
Padding on mobile (larger for touch targets) |
Tooltip
| Variable |
Default |
Description |
--rubik-swatch-tooltip-background |
rgba(0, 0, 0, 0.9) |
Background color |
--rubik-swatch-tooltip-color |
#fff |
Text color |
--rubik-swatch-tooltip-font-size |
12px |
Font size |
--rubik-swatch-tooltip-line-height |
1.4 |
Line height |
--rubik-swatch-tooltip-padding |
6px 12px |
Inner padding |
--rubik-swatch-tooltip-border-radius |
4px |
Border radius |
--rubik-swatch-tooltip-offset |
8px |
Distance from the swatch element |
--rubik-swatch-tooltip-shadow |
0 2px 8px rgba(0, 0, 0, 0.15) |
Box shadow |
--rubik-swatch-tooltip-arrow-size |
5px |
Size of the tooltip arrow |
--rubik-swatch-tooltip-transition-duration |
0.2s |
Fade in/out duration |
--rubik-swatch-tooltip-z-index |
1000 |
Z-index stacking order |
Size chart
| Variable |
Default |
Description |
--rubik-swatch-size-chart-font-size |
14px |
Font size of the size chart link |
--rubik-swatch-size-chart-underline-offset |
5px |
Offset between the size chart link text and its underline |
--rubik-swatch-size-chart-color |
inherit |
Text color of the size chart link |
--rubik-swatch-size-chart-text-decoration |
underline |
Text decoration of the size chart link |
HTML structure
Understanding the DOM structure helps with advanced customization. Here's the complete HTML hierarchy the app generates:
Image swatch structure
<div class="rubik-swatch">
<fieldset class="rubik-swatch__option">
<legend class="rubik-swatch__option-name">
<span class="rubik-swatch__option-label">
<span class="rubik-swatch__option-name-label">Color</span>
<span class="rubik-swatch__option-colon">: </span>
<span class="rubik-swatch__option-name-value">Blue</span>
</span>
<span class="rubik-swatch__size-chart-placeholder"></span>
</legend>
<div class="rubik-swatch__items">
<div class="rubik-swatch__item-wrapper">
<input type="radio" class="rubik-swatch__input" id="..." name="..." value="..." checked>
<label class="rubik-swatch__label rubik-swatch__label--image" for="...">
<img class="rubik-swatch__image" src="..." alt="Blue">
</label>
<span class="rubik-swatch__text-label">Blue</span>
<div class="rubik-swatch__tooltip">Blue</div>
</div>
</div>
</fieldset>
</div>
Pill swatch structure
<div class="rubik-swatch__item-wrapper">
<input type="radio" class="rubik-swatch__input" id="..." name="..." value="...">
<label class="rubik-swatch__label rubik-swatch__label--pill" for="...">
Small
</label>
</div>
Dropdown structure
<div class="rubik-swatch">
<fieldset class="rubik-swatch__option">
<legend class="rubik-swatch__option-name">...</legend>
<select class="rubik-swatch__dropdown">
<option value="small">Small</option>
<option value="medium" selected>Medium</option>
<option value="large">Large</option>
<option value="xl" disabled>XL (Sold out)</option>
</select>
</fieldset>
</div>
Unavailable swatch structure
<!-- Image swatch with unavailable overlay -->
<label class="rubik-swatch__label rubik-swatch__label--image rubik-swatch__label--unavailable" for="...">
<img class="rubik-swatch__image" src="..." alt="Red">
<svg class="rubik-swatch__unavailable-overlay">
<line x1="0" y1="100%" x2="100%" y2="0" stroke="currentColor" stroke-width="1.5" />
</svg>
</label>
<!-- Pill swatch with unavailable overlay -->
<label class="rubik-swatch__label rubik-swatch__label--pill rubik-swatch__label--unavailable" for="...">
XL
<svg class="rubik-swatch__unavailable-overlay">
<line x1="0" y1="100%" x2="100%" y2="0" stroke="currentColor" stroke-width="1.5" />
</svg>
</label>
HTML class reference
For advanced customization, you can target specific elements using CSS classes.
Use these selectors inside your :root, :host block.
Container classes
| Class |
Description |
.rubik-swatch |
Main swatch container |
.rubik-swatch__option |
Fieldset wrapping one option group |
.rubik-swatch__option-name |
Legend element with option label (e.g., "Color: Blue") |
.rubik-swatch__items |
Flex container holding all swatch items |
.rubik-swatch__item-wrapper |
Wrapper around each individual swatch (input + label + tooltip) |
Label classes
| Selector |
Description |
.rubik-swatch__option-name-label |
The option name text (e.g., "Color") |
.rubik-swatch__option-colon |
The colon separator ": " |
.rubik-swatch__option-name-value |
The selected value text (e.g., "Blue") |
Swatch type classes
| Class |
Description |
.rubik-swatch__label |
Base class for all swatch labels |
.rubik-swatch__label--image |
Image swatch variant |
.rubik-swatch__label--pill |
Pill/text swatch variant |
.rubik-swatch__label--unavailable |
Sold-out/unavailable swatch |
Element classes
| Class |
Description |
.rubik-swatch__input |
Hidden radio input |
.rubik-swatch__image |
Image element inside image swatch |
.rubik-swatch__text-label |
Text label below image swatch |
.rubik-swatch__tooltip |
Tooltip element |
.rubik-swatch__unavailable-overlay |
SVG strike-through overlay for sold-out swatches |
.rubik-swatch__dropdown |
Dropdown select element |
.rubik-swatch__size-chart-placeholder |
Size chart link placeholder |
State selectors
| Selector |
Description |
.rubik-swatch__input:checked + .rubik-swatch__label |
Currently selected swatch |
.rubik-swatch__input:disabled + .rubik-swatch__label |
Disabled swatch |
.rubik-swatch__label:hover |
Swatch on hover |
Examples
Rounded image swatches
:root, :host {
--rubik-swatch-image-border-radius: 50%;
--rubik-swatch-image-size: 50px;
--rubik-swatch-image-object-fit: cover;
}
Pill swatch styling
:root, :host {
/* Rounded pills */
--rubik-swatch-pill-border-radius: 20px;
--rubik-swatch-pill-padding: 10px 24px;
/* Custom colors */
--rubik-swatch-pill-background: #f8f8f8;
--rubik-swatch-pill-color: #222;
--rubik-swatch-pill-border-color: #ddd;
/* Selected state */
--rubik-swatch-pill-selected-background: #222;
--rubik-swatch-pill-selected-color: #fff;
--rubik-swatch-pill-selected-border-color: #222;
}
Show text labels below images
:root, :host {
--rubik-swatch-label-display: block;
--rubik-swatch-label-background: transparent;
--rubik-swatch-label-border-color: transparent;
--rubik-swatch-label-color: #555;
}
Center-align swatches
:root, :host {
--rubik-swatch-alignment: center;
--rubik-swatch-text-align: center;
}
Hide option label parts
/* Hide the option name entirely */
:root, :host {
--rubik-swatch-option-name-display: none;
}
/* Or hide just the selected value (keep "Color" but hide ": Blue") */
:root, :host {
--rubik-swatch-option-name-value-display: none;
--rubik-swatch-option-colon-display: none;
}
Dropdown styling
:root, :host {
--rubik-swatch-dropdown-border-radius: 8px;
--rubik-swatch-dropdown-border-color: #ccc;
--rubik-swatch-dropdown-focus-border-color: #2563EB;
--rubik-swatch-dropdown-focus-outline: 2px solid #2563EB;
--rubik-swatch-dropdown-padding: 12px 40px 12px 16px;
}
Remove hover effects
:root, :host {
--rubik-swatch-image-hover-shadow: none;
--rubik-swatch-image-hover-scale: 1;
--rubik-swatch-pill-hover-shadow: none;
--rubik-swatch-transition-duration: 0s;
}
Advanced: target specific elements
/* Make selected swatch label bold */
.rubik-swatch__input:checked + .rubik-swatch__label--image {
border-width: 2px;
border-color: #2563EB;
}
/* Style the option name */
.rubik-swatch__option-name {
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* Custom tooltip style */
:root, :host {
--rubik-swatch-tooltip-background: #2563EB;
--rubik-swatch-tooltip-color: #fff;
--rubik-swatch-tooltip-border-radius: 8px;
}
Quick reference
A compact list of all CSS variables with their default values, organized by category.
Copy variables from here and paste into your custom CSS.
Layout & spacing
--rubik-swatch-margin-top: 5px;
--rubik-swatch-margin-bottom: 5px;
--rubik-swatch-fieldset-margin-top: 10px;
--rubik-swatch-gap: 8px;
--rubik-swatch-margin: 0;
--rubik-swatch-alignment: flex-start;
--rubik-swatch-text-align: left;
--rubik-swatch-transition-duration: 0.2s;
Option labels
--rubik-swatch-option-font-size: 14px;
--rubik-swatch-option-name-color: #333333;
--rubik-swatch-option-name-display: flex;
--rubik-swatch-option-margin-bottom: 8px;
--rubik-swatch-option-name-label-display: inline;
--rubik-swatch-option-colon-display: inline;
--rubik-swatch-option-name-value-display: inline;
Image swatches
--rubik-swatch-image-size: 70px;
--rubik-swatch-image-height: var(--rubik-swatch-image-size);
--rubik-swatch-image-border-width: 1px;
--rubik-swatch-image-border-color: #e5e5e5;
--rubik-swatch-image-border-radius: 0;
--rubik-swatch-image-aspect-ratio: auto;
--rubik-swatch-image-background-color: #ffffff;
--rubik-swatch-image-object-fit: contain;
--rubik-swatch-image-hover-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
--rubik-swatch-image-hover-scale: 1.1;
--rubik-swatch-image-selected-border-color: #333;
--rubik-swatch-image-selected-border-width: 1px;
--rubik-swatch-image-selected-outline: none;
--rubik-swatch-image-selected-outline-offset: 0;
Pill / text swatches
--rubik-swatch-pill-padding: 8px 16px;
--rubik-swatch-pill-border-width: 1px;
--rubik-swatch-pill-border-color: #e5e5e5;
--rubik-swatch-pill-border-radius: 0;
--rubik-swatch-pill-background: #fff;
--rubik-swatch-pill-color: #333;
--rubik-swatch-pill-font-size: 14px;
--rubik-swatch-pill-min-width: 50px;
--rubik-swatch-pill-hover-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
--rubik-swatch-pill-selected-background: #333;
--rubik-swatch-pill-selected-color: #fff;
--rubik-swatch-pill-selected-border-color: #333;
--rubik-swatch-pill-selected-border-width: 1px;
--rubik-swatch-pill-selected-outline: none;
--rubik-swatch-pill-selected-outline-offset: 0;
--rubik-swatch-pill-unavailable-opacity: 0.9;
Text labels
--rubik-swatch-label-display: none;
--rubik-swatch-label-background: #f5f5f5;
--rubik-swatch-label-border-color: #e5e5e5;
--rubik-swatch-label-border: 1px solid #e5e5e5;
--rubik-swatch-label-border-top: 1px solid #e5e5e5;
--rubik-swatch-label-border-bottom: 1px solid #e5e5e5;
--rubik-swatch-label-width: var(--rubik-swatch-image-size);
--rubik-swatch-label-color: #333;
--rubik-swatch-label-font-size: 11px;
--rubik-swatch-label-font-weight: inherit;
--rubik-swatch-label-text-align: center;
--rubik-swatch-label-padding-block: 2px;
--rubik-swatch-label-padding-inline: 4px;
--rubik-swatch-label-flex-grow: 0;
--rubik-swatch-label-text-overflow: ellipsis;
--rubik-swatch-label-white-space: nowrap;
With labels on, the editor sets --rubik-swatch-label-border to none and
--rubik-swatch-label-width to 100%, because the caption box below draws the frame instead.
--rubik-swatch-label-flex-grow becomes 1, which is what makes every label in a row the
same height.
The caption box
--rubik-swatch-caption-display: contents;
--rubik-swatch-caption-border: none;
--rubik-swatch-caption-border-radius: 0;
--rubik-swatch-caption-background: transparent;
--rubik-swatch-caption-gap: 0;
.rubik-swatch__caption is the box around the variant name and its price, so the swatch and everything
written under it read as one card. It draws the left, right and bottom edges and the bottom corner radius; there is
never a top edge, because the swatch above already draws that line. With text labels on, the editor sets
--rubik-swatch-caption-display to flex and moves the border and background here from the
label. --rubik-swatch-caption-gap is the space between the name and the price.
The default is contents, which takes the box out of the layout entirely and leaves the name and price
exactly where they were. That is also what is used when text labels are off and only prices are on, in which case
the price draws its own frame.
Prices
--rubik-swatch-price-display: none;
--rubik-swatch-price-font-size: 11px;
--rubik-swatch-price-font-weight: inherit;
--rubik-swatch-price-color: #333;
--rubik-swatch-price-text-align: center;
--rubik-swatch-price-padding-block: 2px;
--rubik-swatch-price-plus-display: inline;
--rubik-swatch-price-border: none;
--rubik-swatch-price-border-radius: 0;
--rubik-swatch-price-width: var(--rubik-swatch-image-size);
--rubik-swatch-price-plus-display is the + that marks a color whose variants are not
all the same price; set it to none to hide the marker. The border variables are used only when text
labels are off, where the price is the whole caption and frames itself.
Hover and selection effects
--rubik-swatch-image-hover-scale: 1.1;
--rubik-swatch-image-hover-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
--rubik-swatch-pill-hover-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
--rubik-swatch-image-selected-outline: none;
--rubik-swatch-image-selected-outline-offset: 0;
--rubik-swatch-pill-selected-outline: none;
--rubik-swatch-pill-selected-outline-offset: 0;
--rubik-swatch-image-unavailable-opacity: 1;
--rubik-swatch-pill-unavailable-opacity: 0.9;
Carousel
--rubik-swatch-carousel-space: 0px;
--rubik-swatch-carousel-space-inline: 0px;
--rubik-swatch-carousel-nav-mobile-display: none;
--rubik-swatch-carousel-nav-size: 28px;
--rubik-swatch-carousel-nav-border-radius: 50%;
--rubik-swatch-carousel-nav-background: #fff;
--rubik-swatch-carousel-nav-color: #333;
--rubik-swatch-carousel-nav-border-color: #e5e5e5;
--rubik-swatch-carousel-nav-border-width: 1px;
--rubik-swatch-carousel-nav-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
These apply only in the carousel layout. --rubik-swatch-carousel-space is the padding inside the
scrolling row, reserved so a tooltip, a hover zoom or a selection ring is not clipped by the scroll box; the editor
computes it from those settings. The row itself is
.rubik-swatch--carousel .rubik-swatch__items--visual, and the arrows are
.rubik-swatch__carousel-nav--prev and .rubik-swatch__carousel-nav--next.
Sold out / unavailable
--rubik-swatch-unavailable-line-color: #666;
--rubik-swatch-image-unavailable-line-color: #666;
--rubik-swatch-pill-unavailable-line-color: #666;
Dropdown
--rubik-swatch-dropdown-min-width: 150px;
--rubik-swatch-dropdown-max-width: 100%;
--rubik-swatch-dropdown-padding: 10px 40px 10px 16px;
--rubik-swatch-dropdown-font-size: 14px;
--rubik-swatch-dropdown-font-family: inherit;
--rubik-swatch-dropdown-line-height: 1.5;
--rubik-swatch-dropdown-color: #333;
--rubik-swatch-dropdown-background: #fff;
--rubik-swatch-dropdown-border-width: 1px;
--rubik-swatch-dropdown-border-color: #e5e5e5;
--rubik-swatch-dropdown-border-radius: 0;
--rubik-swatch-dropdown-transition: 0.2s;
--rubik-swatch-dropdown-shadow: none;
/* Hover */
--rubik-swatch-dropdown-hover-border-color: #ccc;
--rubik-swatch-dropdown-hover-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
/* Focus */
--rubik-swatch-dropdown-focus-outline: 2px solid #333;
--rubik-swatch-dropdown-focus-outline-offset: 2px;
--rubik-swatch-dropdown-focus-border-color: #333;
--rubik-swatch-dropdown-focus-shadow: 0 0 0 3px rgba(0, 0, 0, 0.05);
/* Disabled */
--rubik-swatch-dropdown-disabled-opacity: 0.6;
--rubik-swatch-dropdown-disabled-background: #f5f5f5;
/* Options */
--rubik-swatch-dropdown-option-padding: 8px;
--rubik-swatch-dropdown-option-color: inherit;
--rubik-swatch-dropdown-option-background: #fff;
--rubik-swatch-dropdown-option-disabled-color: #999;
--rubik-swatch-dropdown-option-disabled-style: italic;
--rubik-swatch-dropdown-option-selected-background: #f0f0f0;
--rubik-swatch-dropdown-option-selected-weight: 600;
/* Mobile */
--rubik-swatch-dropdown-mobile-padding: 12px 40px 12px 16px;
Tooltip
--rubik-swatch-tooltip-background: rgba(0, 0, 0, 0.9);
--rubik-swatch-tooltip-color: #fff;
--rubik-swatch-tooltip-font-size: 12px;
--rubik-swatch-tooltip-line-height: 1.4;
--rubik-swatch-tooltip-padding: 6px 12px;
--rubik-swatch-tooltip-border-radius: 4px;
--rubik-swatch-tooltip-offset: 8px;
--rubik-swatch-tooltip-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
--rubik-swatch-tooltip-arrow-size: 5px;
--rubik-swatch-tooltip-transition-duration: 0.2s;
--rubik-swatch-tooltip-z-index: 1000;
Size chart
--rubik-swatch-size-chart-font-size: 14px;
--rubik-swatch-size-chart-underline-offset: 5px;
--rubik-swatch-size-chart-color: inherit;
--rubik-swatch-size-chart-text-decoration: underline;
Tips & best practices
- Use
:root, :host as your wrapping selector. This ensures your styles work whether the swatches are rendered normally or inside a Shadow DOM.
- Prefer CSS variables over class selectors when possible. Variables are more reliable and won't break if internal HTML structure changes.
- Use browser dev tools to inspect the swatch elements. In Chrome, open DevTools, find the
.rubik-swatch element, and explore its children to see the live structure.
- 4000 character limit - the custom CSS field has a 4000 character limit. Keep your CSS concise and avoid unnecessary whitespace.
- Start simple - override one or two variables at a time to understand their effect before adding more.
- Test on both desktop and mobile - some variables have mobile-specific overrides (especially dropdown padding and font size).
- Check specificity - if your class-based styles aren't applying, you may need to increase specificity by chaining selectors.
Learn more from our blog