Documentation

Style overrides

One overlay at a time

Theme style layer paints over Horizon CSS. The embed loads a shared selector baseline, then exactly one style theme. Atelier and Linen are the current themes. Turn the embed off to restore Horizon styles.

Turn one on

  1. Online Store → Themes → Customize → Theme settings → App embeds.
  2. Enable Theme style layer.
  3. Under Style override, set Active theme to Atelier or Linen. The default is Atelier.

The select is exclusive. Only the chosen file loads, so two overrides cannot apply together. A value the embed does not recognize falls back to Atelier.

What the embed loads

  • vendr-theme-style-layer.css — empty Horizon selectors, shared by every style theme. The embed schema loads it in the document head, and the block loads it again before </body>.
  • One theme file: vendr-theme-atelier.css or vendr-theme-linen.css.
  • data-vendr-style-theme on <html>, set to the active handle.

Keep the body <link> for the baseline. Shopify can inject the head stylesheet before Horizon {% stylesheet %} CSS, so the body copy is the one that wins.

Add a style override

A new Active theme is a CSS asset plus a branch in the embed. Use a lowercase handle with no spaces, and use that same handle in the filename, the select value, and the Liquid check.

1. Theme CSS

Add extensions/vendr-theme/assets/vendr-theme-{handle}.css. Brand rules live here. Leave the shared baseline empty. Horizon buttons read --button-background-color; set that variable and background-color, including :hover, so a hover state cannot restore the Horizon color.

extensions/vendr-theme/assets/vendr-theme-noir.css

/**
 * Loaded only when Theme style layer is on and Active theme is Noir.
 */
.button,
.button-secondary,
.button-custom,
button.shopify-payment-button__button--unbranded,
.button:hover,
.button-secondary:hover,
.button-custom:hover,
button.shopify-payment-button__button--unbranded:hover:not([disabled]) {
  --button-color: #ffffff;
  --button-background-color: #111111;
  --button-border-color: #111111;
  background-color: #111111;
  color: #ffffff;
}

2. Active theme option

In blocks/vendr-theme-style-layer.liquid, add the handle to the select. The label is the name merchants see.

blocks/vendr-theme-style-layer.liquid

{
  "value": "noir",
  "label": "Noir"
}

3. Load that file only

Allow the handle, then map it to the CSS filename. Anything else still falls back to Atelier. The existing script already writes data-vendr-style-theme from this value.

{% liquid
  assign style_theme = block.settings.style_theme
  if style_theme != 'atelier' and style_theme != 'linen' and style_theme != 'noir'
    assign style_theme = 'atelier'
  endif

  if style_theme == 'linen'
    assign theme_css = 'vendr-theme-linen.css'
  elsif style_theme == 'noir'
    assign theme_css = 'vendr-theme-noir.css'
  else
    assign theme_css = 'vendr-theme-atelier.css'
  endif
%}

Put toggleable brand rules in this CSS file. A store stylesheet rendered from the theme layout stays on for every shopper and loads after the style layer, so it cannot be switched off from App embeds.

After a Horizon update

Regenerate the empty selector baseline after merging upstream Horizon. The script reads theme assets/*.css and {% stylesheet %} blocks, then rewrites the block between the baseline markers in vendr-theme-style-layer.css. Leave that generated block as the script wrote it.

node scripts/extract-horizon-selectors.mjs /path/to/horizon-theme

With no path, the script uses VENDR_THEME_ROOT, then the default theme checkout next to the app.