Rubik Variant Images & Swatch

Custom CSS Reference Rubik Variant Images & Swatch

← 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.

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.

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 table 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

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

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

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 url(...svg) Custom arrow icon (SVG data URL)
--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-font-size 16px Font size on mobile (larger for touch targets)
--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-margin-left 10px Left margin of the size chart link
--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: table;
--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-color: #333;
--rubik-swatch-label-text-overflow: ellipsis;
--rubik-swatch-label-white-space: nowrap;

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-font-size: 16px;
--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-margin-left: 10px;
--rubik-swatch-size-chart-color: inherit;
--rubik-swatch-size-chart-text-decoration: underline;

Tips & best practices