← Back to documentation
Introduction
Custom CSS allows you to fully customize the appearance of your combined listings swatches.
You can change colors, sizes, spacing, fonts, and more to match your store's design.
The swatches use Shadow DOM, which means their styles are isolated from your theme's styles.
This prevents conflicts but also means you need to use the custom CSS feature to override default styles.
Getting started
All custom CSS must be wrapped in the :host selector. This targets the swatch component container.
Try this example to create a warm, earthy color scheme:
:host {
--rcl-group-label-color: #C4785A;
--rcl-swatch-active-border-color: #C4785A;
--rcl-swatch-border-offset-color: #F5F0E1;
--rcl-swatch-border-color: #D4C4B0;
--rcl-swatch-media-bg: #F5F0E1;
}
Want something more eye-catching? Try this rainbow glow effect on the selected swatch:
@keyframes rainbow-glow {
0% { box-shadow: 0 0 0 2px #f4a5a5, 0 0 12px #f4a5a5; }
25% { box-shadow: 0 0 0 2px #f9d89a, 0 0 12px #f9d89a; }
50% { box-shadow: 0 0 0 2px #a8d5a2, 0 0 12px #a8d5a2; }
75% { box-shadow: 0 0 0 2px #a5c4f4, 0 0 12px #a5c4f4; }
100% { box-shadow: 0 0 0 2px #f4a5a5, 0 0 12px #f4a5a5; }
}
:host .rcl__swatch--active {
animation: rainbow-glow 3s linear infinite;
}
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.
Layout & container
| Variable |
Default |
Description |
--rcl-display |
block |
Display mode of the component |
--rcl-margin-top |
10px |
Top margin of the container |
--rcl-margin-bottom |
10px |
Bottom margin of the container |
--rcl-margin-left |
0px |
Left margin of the container |
--rcl-margin-right |
0px |
Right margin of the container |
--rcl-font-family |
inherit |
Font family (inherits from theme) |
--rcl-groups-gap |
10px |
Spacing between multiple swatch groups |
--rcl-group-margin-bottom |
5px |
Bottom margin of each group |
--rcl-grid-gap |
9px |
Gap between swatches in the grid |
--rcl-grid-padding-block |
5px |
Vertical (top/bottom) padding of the grid |
--rcl-grid-padding-inline |
1px |
Horizontal (left/right) padding of the grid |
--rcl-grid-align |
flex-start |
Horizontal alignment: flex-start (left), center, flex-end (right) |
--rcl-container-padding-block |
1px |
Vertical (top/bottom) inner padding of the swatch container |
--rcl-container-padding-inline |
1px |
Horizontal (left/right) inner padding of the swatch container |
Group label
| Variable |
Default |
Description |
--rcl-group-label-gap |
5px |
Gap below the group label |
--rcl-group-label-font-size |
14px |
Font size of group label |
--rcl-group-label-font-weight |
500 |
Font weight of group label |
--rcl-group-label-color |
#333333 |
Text color of group label |
--rcl-group-label-margin |
0 0 5px 0 |
Margin around the group label |
Visual swatch (polaroid card)
| Variable |
Default |
Description |
--rcl-swatch-width |
60px |
Width of each swatch |
--rcl-swatch-bg |
#fff |
Background color of swatch |
--rcl-swatch-border-width |
1px |
Border width of swatch |
--rcl-swatch-border-color |
#e5e5e5 |
Border color of swatch |
--rcl-swatch-border-radius |
9px |
Border radius of swatch |
--rcl-swatch-border-offset |
2px |
Gap between content and outline |
--rcl-swatch-border-offset-color |
#ffffff |
Color of the offset gap |
--rcl-swatch-transition |
transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease |
Transition for hover effects |
Swatch hover & active states
| Variable |
Default |
Description |
--rcl-swatch-hover-border-color |
#ccc |
Border color on hover |
--rcl-swatch-hover-shadow |
0 4px 12px rgba(0, 0, 0, 0.15) |
Box shadow on hover |
--rcl-swatch-hover-transform |
translateY(-2px) |
Transform (lift) on hover |
--rcl-swatch-active-border-color |
#000000 |
Border color when selected |
Swatch media (image/color)
| Variable |
Default |
Description |
--rcl-swatch-media-aspect-ratio |
1 |
Aspect ratio of image area (1 = square) |
--rcl-swatch-image-fit |
contain |
How image fits: contain, cover, fill |
--rcl-swatch-media-bg |
#ffffff |
Background color of image area |
Swatch info (label + price)
| Variable |
Default |
Description |
--rcl-swatch-info-padding |
3px 5px |
Padding around label/price area |
--rcl-swatch-info-gap |
1px |
Gap between info elements |
--rcl-swatch-info-align |
left |
Text alignment: left, center, right |
--rcl-swatch-info-bg |
#ffffff |
Background color of label/price area |
--rcl-swatch-label-font-size |
9px |
Font size of swatch label |
--rcl-swatch-label-font-weight |
500 |
Font weight of swatch label |
--rcl-swatch-label-color |
#333333 |
Text color of swatch label |
--rcl-swatch-label-line-height |
1.3 |
Line height of label text |
--rcl-swatch-label-max-rows |
1 |
Max rows before truncation |
--rcl-swatch-price-font-size |
8px |
Font size of price |
--rcl-swatch-price-font-weight |
500 |
Font weight of price |
--rcl-swatch-price-color |
#000000 |
Text color of price |
--rcl-label-price-gap |
2px |
Gap between label and price |
Out-of-stock appearance
| Variable |
Default |
Description |
--rcl-swatch-unavailable-opacity |
0.5 |
Opacity of out-of-stock swatches |
--rcl-out-of-stock-line-color |
#666666 |
Color of diagonal strike-through line |
--rcl-out-of-stock-line-opacity |
0.7 |
Opacity of strike-through line |
--rcl-out-of-stock-line-width |
2px |
Width of strike-through line |
Overflow indicator (+n)
| Variable |
Default |
Description |
--rcl-swatch-overflow-bg |
#f5f5f5 |
Background of "+n more" indicator |
--rcl-swatch-overflow-color |
#666666 |
Text color of "+n more" indicator |
--rcl-swatch-overflow-font-size |
min(14px, calc(var(--rcl-swatch-width) / 2)) |
Font size of overflow text |
--rcl-swatch-overflow-font-weight |
500 |
Font weight of overflow text |
--rcl-swatch-overflow-hover-bg |
#e8e8e8 |
Background on hover |
--rcl-swatch-overflow-hover-color |
#333333 |
Text color on hover |
Button swatch
| Variable |
Default |
Description |
--rcl-button-border-radius |
4px |
Border radius of button |
--rcl-button-bg-color |
#ffffff |
Background color |
--rcl-button-text-color |
#333333 |
Text color |
--rcl-button-font-size |
14px |
Font size |
--rcl-button-padding |
8px 16px |
Inner padding |
--rcl-button-border-color |
#e5e5e5 |
Border color |
--rcl-button-border-width |
1px |
Border width |
--rcl-button-text-align |
center |
Text alignment: flex-start (left), center, flex-end (right) |
Button hover & active states
| Variable |
Default |
Description |
--rcl-button-hover-bg-color |
#f5f5f5 |
Background on hover |
--rcl-button-hover-border-color |
#ccc |
Border color on hover |
--rcl-button-active-border-color |
#000000 |
Border color when selected (border style) |
Button fill style (invert)
| Variable |
Default |
Description |
--rcl-button-invert-bg-color |
#000 |
Background when selected (fill style) |
--rcl-button-invert-text-color |
#fff |
Text color when selected (fill style) |
Button image
| Variable |
Default |
Description |
--rcl-button-image-size |
32px |
Size of image inside button |
--rcl-button-image-border-radius |
50% |
Border radius of button image |
--rcl-button-image-fit |
contain |
How image fits: contain, cover |
--rcl-button-image-gap |
5px |
Gap between image and text |
--rcl-button-image-bg-color |
#ffffff |
Background color of image container |
Button out-of-stock
| Variable |
Default |
Description |
--rcl-button-unavailable-opacity |
0.5 |
Opacity of out-of-stock buttons |
--rcl-button-out-of-stock-line-color |
#666666 |
Strike-through line color |
--rcl-button-out-of-stock-line-opacity |
0.7 |
Strike-through line opacity |
--rcl-button-out-of-stock-line-width |
2px |
Strike-through line width |
Dropdown
| Variable |
Default |
Description |
--rcl-dropdown-width |
100% |
Width of dropdown |
--rcl-dropdown-border-radius |
4px |
Border radius |
--rcl-dropdown-bg-color |
#ffffff |
Background color |
--rcl-dropdown-text-color |
#333333 |
Text color |
--rcl-dropdown-font-size |
14px |
Font size |
--rcl-dropdown-padding |
10px 12px |
Inner padding |
--rcl-dropdown-border-color |
#e5e5e5 |
Border color |
--rcl-dropdown-border-width |
1px |
Border width |
--rcl-dropdown-arrow-color |
#666 |
Color of dropdown arrow |
Dropdown hover & focus
| Variable |
Default |
Description |
--rcl-dropdown-hover-border-color |
#ccc |
Border color on hover |
--rcl-dropdown-focus-border-color |
#000 |
Border color when focused |
Carousel navigation
| Variable |
Default |
Description |
--rcl-carousel-gap |
8px |
Gap between carousel slides |
--rcl-carousel-nav-size |
27px |
Size of navigation buttons |
--rcl-carousel-nav-border-radius |
50% |
Border radius (50% = circle) |
--rcl-carousel-nav-blur |
4px |
Backdrop blur amount |
--rcl-carousel-nav-bg |
#fff |
Background color |
--rcl-carousel-nav-color |
#333 |
Arrow color |
--rcl-carousel-nav-border |
1px solid #e5e5e5 |
Border style |
--rcl-carousel-nav-shadow |
0 2px 4px rgba(0, 0, 0, 0.1) |
Box shadow |
--rcl-carousel-nav-hover-bg |
#f5f5f5 |
Background on hover |
Tooltip
| Variable |
Default |
Description |
--rcl-tooltip-bg |
rgba(0, 0, 0, 0.85) |
Background color |
--rcl-tooltip-color |
#fff |
Text color |
--rcl-tooltip-font-size |
12px |
Font size |
--rcl-tooltip-padding |
6px 10px |
Inner padding |
--rcl-tooltip-border-radius |
4px |
Border radius |
--rcl-tooltip-offset |
8px |
Distance from trigger element |
Placeholder
| Variable |
Default |
Description |
--rcl-placeholder-bg |
#e5e5e5 |
Background when no image |
--rcl-placeholder-color |
#888 |
Text/icon color |
--rcl-placeholder-font-size |
14px |
Font size |
HTML structure
Understanding the DOM structure helps with advanced customization. Here's the complete HTML hierarchy inside the shadow DOM:
Visual swatch structure
<rubik-combined-listings>
#shadow-root
<div class="rcl">
<div class="rcl__group">
<p class="rcl__group-label">
<span class="rcl__group-label-option-name">Color</span>
<span class="rcl__group-label-separator">: </span>
<span class="rcl__group-label-selected-value">Black</span>
</p>
<div class="rcl__grid">
<a class="rcl__swatch rcl__swatch--active" href="...">
<div class="rcl__swatch-media">
<!-- One of these based on image source: -->
<img class="rcl__swatch-image" src="..." alt="...">
<!-- OR for color swatches: -->
<svg class="rcl__swatch-color">...</svg>
<!-- OR if no image available: -->
<svg class="rcl__swatch-placeholder">...</svg>
</div>
<div class="rcl__swatch-info">
<span class="rcl__swatch-label">Product Name</span>
<span class="rcl__swatch-price">$99.00</span>
</div>
</a>
<a class="rcl__swatch rcl__swatch--unavailable" href="...">
<div class="rcl__swatch-media">
<img class="rcl__swatch-image" src="..." alt="...">
<!-- Diagonal line overlay for out-of-stock: -->
<svg class="rcl__swatch-unavailable-line">...</svg>
</div>
<div class="rcl__swatch-info">...</div>
</a>
<!-- Overflow indicator when max swatches reached: -->
<div class="rcl__swatch rcl__swatch--overflow">+3</div>
</div>
</div>
</div>
</rubik-combined-listings>
Button swatch structure
<a class="rcl__swatch rcl__swatch--button rcl__swatch--active" href="...">
<!-- Optional image (when "Show image" is enabled): -->
<div class="rcl__button-image">
<img src="..." alt="...">
</div>
<div class="rcl__button-content">
<span class="rcl__button-label">Black</span>
<span class="rcl__button-price">$99.00</span>
</div>
</a>
<!-- With fill/invert active style: -->
<a class="rcl__swatch rcl__swatch--button rcl__swatch--button-invert rcl__swatch--active">...</a>
<!-- With image enabled: -->
<a class="rcl__swatch rcl__swatch--button rcl__swatch--button-with-image">...</a>
Dropdown structure
<div class="rcl__dropdown-container">
<select class="rcl__dropdown">
<option value="black" selected>Black - $99.00</option>
<option value="white">White - $99.00</option>
</select>
</div>
Carousel layout structure
<div class="rcl__group">
<p class="rcl__group-label">...</p>
<div class="swiper rcl__carousel">
<div class="swiper-wrapper">
<div class="swiper-slide">
<a class="rcl__swatch">...</a>
</div>
<div class="swiper-slide">
<a class="rcl__swatch">...</a>
</div>
</div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
</div>
HTML class reference
For advanced customization, you can target specific elements using CSS classes.
Use these selectors inside your :host block.
Container classes
| Class |
Description |
.rcl |
Main container |
.rcl__group |
Group container |
.rcl__group-label |
Group label (e.g., "Color:") |
.rcl__grid |
Grid layout container |
.rcl__carousel |
Carousel layout container |
Swatch classes
| Class |
Description |
.rcl__swatch |
Individual swatch |
.rcl__swatch--active |
Currently selected swatch |
.rcl__swatch--unavailable |
Out-of-stock swatch |
.rcl__swatch--overflow |
"+n more" indicator |
.rcl__swatch-media |
Image/color area |
.rcl__swatch-image |
Product image |
.rcl__swatch-color |
Color swatch element |
.rcl__swatch-info |
Label + price container |
.rcl__swatch-label |
Swatch label text |
.rcl__swatch-price |
Swatch price text |
Button swatch classes
| Class |
Description |
.rcl__swatch--button |
Button-style swatch |
.rcl__swatch--button-invert |
Button with fill active style |
.rcl__swatch--button-with-image |
Button containing an image |
.rcl__button-image |
Image container inside button |
.rcl__button-content |
Content container inside button |
.rcl__button-label |
Label text inside button |
.rcl__button-price |
Price text inside button |
Dropdown classes
| Class |
Description |
.rcl__dropdown-container |
Dropdown wrapper |
.rcl__dropdown |
Select element |
Modifier classes
| Class |
Description |
.rcl--hide-label |
Hides swatch labels |
.rcl--hide-price |
Hides swatch prices |
.rcl--hide-option-name |
Hides "Color:" in group label |
.rcl--hide-selected-value |
Hides selected value in group label |
.rcl--hide-button-price |
Hides price on button swatches |
Examples
Change label color and size
:host {
--rcl-swatch-label-color: #1a1a1a;
--rcl-swatch-label-font-size: 11px;
--rcl-swatch-label-font-weight: 600;
}
Adjust swatch width and spacing
:host {
--rcl-swatch-width: 80px;
--rcl-grid-gap: 12px;
}
Customize border colors
:host {
/* Normal border */
--rcl-swatch-border-color: #ddd;
/* Hover border */
--rcl-swatch-hover-border-color: #999;
/* Selected border */
--rcl-swatch-active-border-color: #2c6ecb;
}
Style out-of-stock swatches
:host {
/* Make out-of-stock swatches more visible */
--rcl-swatch-unavailable-opacity: 0.7;
/* Red strike-through line */
--rcl-out-of-stock-line-color: #cc0000;
--rcl-out-of-stock-line-width: 2px;
}
Button swatch styling
:host {
/* Rounded buttons */
--rcl-button-border-radius: 20px;
/* Custom colors */
--rcl-button-bg-color: #f8f8f8;
--rcl-button-text-color: #222;
--rcl-button-border-color: #ccc;
/* Active state (fill style) */
--rcl-button-invert-bg-color: #2c6ecb;
--rcl-button-invert-text-color: #fff;
}
Dropdown styling
:host {
--rcl-dropdown-border-radius: 8px;
--rcl-dropdown-border-color: #ccc;
--rcl-dropdown-focus-border-color: #2c6ecb;
--rcl-dropdown-padding: 12px 16px;
}
Remove hover lift effect
:host {
--rcl-swatch-hover-transform: none;
--rcl-swatch-hover-shadow: none;
}
Center-align swatch labels
:host {
--rcl-swatch-info-align: center;
}
Advanced: target specific elements
/* Make selected swatch label bold */
:host .rcl__swatch--active .rcl__swatch-label {
font-weight: 700;
}
/* Add background to group label */
:host .rcl__group-label {
background: #f5f5f5;
padding: 8px 12px;
border-radius: 4px;
}
Tips & best practices
- Prefer CSS variables over class selectors when possible. Variables are more reliable and won't break if internal HTML structure changes.
- Test on both desktop and mobile - each has its own custom CSS field in the visual settings editor.
- Use browser dev tools to inspect the shadow DOM. In Chrome, open DevTools, find the
<rubik-combined-listings> element, and expand its #shadow-root to see the internal structure.
- Start simple - override one or two variables at a time to understand their effect.
- Check specificity - if your styles aren't applying, you may need to increase specificity by chaining selectors.
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
--rcl-display: block;
--rcl-margin-top: 10px;
--rcl-margin-bottom: 10px;
--rcl-margin-left: 0px;
--rcl-margin-right: 0px;
--rcl-font-family: inherit;
--rcl-groups-gap: 10px;
--rcl-group-margin-bottom: 5px;
--rcl-grid-gap: 9px;
--rcl-grid-padding-block: 5px;
--rcl-grid-padding-inline: 1px;
--rcl-grid-align: flex-start;
--rcl-container-padding-block: 1px;
--rcl-container-padding-inline: 1px;
Group label
--rcl-group-label-gap: 5px;
--rcl-group-label-font-size: 14px;
--rcl-group-label-font-weight: 500;
--rcl-group-label-color: #333333;
Visual swatch
--rcl-swatch-width: 60px;
--rcl-swatch-bg: #fff;
--rcl-swatch-border-width: 1px;
--rcl-swatch-border-color: #e5e5e5;
--rcl-swatch-border-radius: 9px;
--rcl-swatch-border-offset: 2px;
--rcl-swatch-border-offset-color: #ffffff;
--rcl-swatch-hover-border-color: #ccc;
--rcl-swatch-hover-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
--rcl-swatch-hover-transform: translateY(-2px);
--rcl-swatch-active-border-color: #000000;
Swatch media
--rcl-swatch-media-aspect-ratio: 1;
--rcl-swatch-image-fit: contain;
--rcl-swatch-media-bg: #ffffff;
Swatch label & price
--rcl-swatch-info-padding: 3px 5px;
--rcl-swatch-info-align: left;
--rcl-swatch-info-bg: #ffffff;
--rcl-swatch-label-font-size: 9px;
--rcl-swatch-label-font-weight: 500;
--rcl-swatch-label-color: #333333;
--rcl-swatch-label-line-height: 1.3;
--rcl-swatch-label-max-rows: 1;
--rcl-swatch-price-font-size: 8px;
--rcl-swatch-price-font-weight: 500;
--rcl-swatch-price-color: #000000;
--rcl-label-price-gap: 2px;
Out-of-stock
--rcl-swatch-unavailable-opacity: 0.5;
--rcl-out-of-stock-line-color: #666666;
--rcl-out-of-stock-line-opacity: 0.7;
--rcl-out-of-stock-line-width: 2px;
Button swatch
--rcl-button-border-radius: 4px;
--rcl-button-bg-color: #ffffff;
--rcl-button-text-color: #333333;
--rcl-button-font-size: 14px;
--rcl-button-padding: 8px 16px;
--rcl-button-border-color: #e5e5e5;
--rcl-button-border-width: 1px;
--rcl-button-text-align: center;
--rcl-button-hover-bg-color: #f5f5f5;
--rcl-button-hover-border-color: #ccc;
--rcl-button-active-border-color: #000000;
--rcl-button-invert-bg-color: #000;
--rcl-button-invert-text-color: #fff;
--rcl-button-image-size: 32px;
--rcl-button-image-border-radius: 50%;
--rcl-button-image-fit: contain;
--rcl-button-image-gap: 5px;
--rcl-button-image-bg-color: #ffffff;
Dropdown
--rcl-dropdown-width: 100%;
--rcl-dropdown-border-radius: 4px;
--rcl-dropdown-bg-color: #ffffff;
--rcl-dropdown-text-color: #333333;
--rcl-dropdown-font-size: 14px;
--rcl-dropdown-padding: 10px 12px;
--rcl-dropdown-border-color: #e5e5e5;
--rcl-dropdown-border-width: 1px;
--rcl-dropdown-arrow-color: #666;
--rcl-dropdown-hover-border-color: #ccc;
--rcl-dropdown-focus-border-color: #000;
Carousel
--rcl-carousel-gap: 8px;
--rcl-carousel-nav-size: 27px;
--rcl-carousel-nav-border-radius: 50%;
--rcl-carousel-nav-blur: 4px;
--rcl-carousel-nav-bg: #fff;
--rcl-carousel-nav-color: #333;
--rcl-carousel-nav-border: 1px solid #e5e5e5;
--rcl-carousel-nav-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
--rcl-carousel-nav-hover-bg: #f5f5f5;
Tooltip
--rcl-tooltip-bg: rgba(0, 0, 0, 0.85);
--rcl-tooltip-color: #fff;
--rcl-tooltip-font-size: 12px;
--rcl-tooltip-padding: 6px 10px;
--rcl-tooltip-border-radius: 4px;
--rcl-tooltip-offset: 8px;