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
- Online Store → Themes → Customize → Theme settings → App embeds.
- Enable Theme style layer.
- 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.cssorvendr-theme-linen.css. data-vendr-style-themeon<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.