Theming & parts reference
Style every Envie component from your own CSS — parts, state attributes, custom properties, and the styling contract behind them.
This page is the complete styling surface of the Envie components: what you can target, and the rules that keep it stable.
The contract
The components ship no styles beyond :host { display: inline-block }. No theme, no reset, no
opinion. Styling always comes from outside — your theme CSS, your app's stylesheet — through three
stable surfaces:
- Parts — internal elements exposed via
::part(). - State attributes — reflected on the host, so plain attribute selectors work.
- Custom properties — a handful of tokens, all inheriting by default.
These are covered by the same stability promise as the API: they never change meaning within a major version.
Parts
| Component | Part | What it is |
|---|---|---|
<envie-button> | button | The real <button> element |
<envie-button> | label | Text wrapper inside the button |
<envie-badge> | badge | The count wrapper |
<envie-share> | button, label | Same shape as the save button |
envie-button::part(button) {
border: 1px solid currentColor;
border-radius: 999px;
padding: 0.5rem 1rem;
background: transparent;
cursor: pointer;
}State attributes
Reflected on the host element — no JavaScript needed to react to them:
| Attribute | On | Meaning |
|---|---|---|
saved | envie-button | The product is in the wishlist |
busy | envie-button, envie-share | A request is in flight |
disabled | envie-button | Interaction disabled |
count | envie-badge | Current item count (stringified) |
empty | envie-list | Nothing to show |
loading | envie-list | First render not yet complete |
hidden | envie-share | Sharing unavailable for this shop or list |
envie-button[saved]::part(button) {
background: currentColor;
}
envie-button[busy] {
opacity: 0.6;
pointer-events: none;
}
envie-badge[count="0"] {
display: none;
}Custom properties
| Token | Purpose |
|---|---|
--envie-icon-size | Icon dimensions |
--envie-color | Resting color |
--envie-color-active | Saved-state color |
--envie-transition | State-change transition |
All default to inherited/neutral values, so an unstyled component picks up your typography and colors instead of fighting them.
Wishlist items are your markup
<envie-list> renders items into light DOM — your theme CSS applies to them directly, no
parts needed. You control the item markup two ways:
A theme section (Liquid stores) — set card-section to one of your theme's section filenames
and every saved product renders through your theme's own product-card section:
<envie-list card-section="product-card"></envie-list>A template (full control) — provide the item markup yourself; elements carrying data-envie-*
attributes are filled per item:
<envie-list>
<template slot="item">
<div class="my-card">
<a data-envie-link><img data-envie-image alt="" /></a>
<p data-envie-title></p>
<envie-button data-envie-toggle></envie-button>
</div>
</template>
</envie-list>| Attribute | Filled with |
|---|---|
data-envie-link | href to the product page |
data-envie-image | Product image src |
data-envie-title | Product title text |
data-envie-toggle | Wired as this item's save button |
A product that no longer resolves gets data-envie-unavailable on the card's root instead of
vanishing — style it as you see fit.
When both are present, the section wins; a product the section can't render falls back to the template rather than blanking the list.
Liquid theme blocks and .envie-styled
The theme app blocks (Wishlist button, badge, page) default to Use Envie's appearance — a small
stylesheet owned by the app embed, applied only to elements carrying the envie-styled class. Turn
the toggle off and the block renders the bare element for your CSS.
A hand-written tag never gets that class, so the appearance settings never fight your stylesheet. Rule of thumb: blocks look finished for merchants; tags are raw for developers.
A starting point
@getenvie/components/starter.css is an optional, documented stylesheet with sensible defaults for
all four components — import it, copy from it, or ignore it:
@import "@getenvie/components/starter.css";Common mistakes
- Styling the host instead of the part.
envie-button { background: … }paints the host box, not the button. Useenvie-button::part(button). - Expecting styles to cross the shadow boundary. Only parts, attributes, and custom properties do. That's the point: your CSS can never break our internals, and ours doesn't exist.
- Not sizing the button box. Give the host fixed dimensions in your CSS (the theme blocks already do) so layout doesn't shift when the element upgrades.