Skip to main content

Custom “Add to Wishlist” Buttons

Updated this week

Custom “Add to Wishlist” buttons let you drop the wishlist action anywhere in your theme—collection grids, quick-view modals, blog posts, even marketing pop-ups—without writing JavaScript.

1 · Quick-paste template

<button class="wishlist-btn"
aria-label="Add to Wishlist"
data-product-handle="{{ product.handle }}"
data-product-id="{{ product.id }}"
data-variant-id="{{ product.selected_or_first_available_variant.id }}"
data-customer-id="{{ customer.id }}"
data-icon-type="icon_heart"
data-icon-position="before"
data-success-text="Saved to Wishlist">
Add to Wishlist
</button>

Place this anywhere in your theme.

2 · Attribute cheat-sheet

attribute

required

example

purpose

data-product-handle

yes

winter-parka

Product handle

data-success-text

no

Saved!

Label when item is saved

data-icon-type

no

icon_heart (default) | icon_star | icon_bookmark | icon_gift | icon_plus | custom | none

Built-in SVG or keep your own markup

data-icon-position

no

before (default) | after

Icon before/after text

data-text-hidden

no

true | false

true → script never edits the label

optional IDs

no

numeric

Available for analytics tracking

3 · Design recipes

Icon after the label

<button class="wishlist-btn"
data-product-handle="{{ product.handle }}"
data-icon-position="after">
Add to List
</button>

Icon-only button

<button class="wishlist-btn"
aria-label="Add to Wishlist"
data-product-handle="{{ product.handle }}"
data-icon-type="icon_star"
data-text-hidden="true"></button>

Keep your own SVG & text

<button class="wishlist-btn"
data-product-handle="{{ product.handle }}"
data-icon-type="custom"
data-text-hidden="true">
<svg class="my-heart" width="20" height="20"></svg>
<span class="visually-hidden">Add to Wishlist</span>
</button>

4 · Styling hooks

.wishlist-btn           { transition: background .2s ease; }
.wishlist-btn.success { background: var(--brand); color: #fff; }

.wishlist-btn-icon svg { width: 1em; height: 1em; pointer-events: none; }

.wishlist-btn-icon + .wishlist-btn-label { margin-left: .35em; }
.wishlist-btn-label + .wishlist-btn-icon { margin-left: .35em; }

5 · Accessibility

requirement

how to implement

why

Descriptive label

aria-label="Add {{ product.title }} to Wishlist"

Announces purpose even if text is hidden or icon-only

Keyboard focus

Button is a native <button> → receives focus automatically

Enables tabbing without extra JS

Visible outline

Use theme focus styles (<code>:focus-visible</code>) or add .wishlist-btn:focus outline

Lets keyboard users see where they are

Colour contrast

Ensure default and .success states meet WCAG AA (4.5 : 1 text contrast)

Visible for low-vision customers

Screen-reader updates

Label changes (“Add” → “Saved”) are within the same element; most screen-readers announce the new text automatically

Confirms action without extra ARIA live regions

Icon semantics

Built-in SVGs have aria-hidden="true" so only the label is spoken

Prevents redundant “heart, Add to Wishlist” announcements

Hidden text pattern

If using data-text-hidden="true" include a visually hidden span or rely on aria-label

Keeps meaning for assistive tech

Pointer target size

Keep button at least 44 × 44 px (Apple HIG / WCAG AAA target size)

Easier for touch users

Example with hidden text and accessible name

<button class="wishlist-btn"
aria-label="Add {{ product.title }} to Wishlist"
data-product-handle="{{ product.handle }}"
data-icon-type="icon_plus"
data-text-hidden="true">
</button>

6 · Troubleshooting

symptom

cause

solution

Button opens product page

Wrapped inside a stretched link

Move button outside the <a> or stop propagation

No icon appears

Wrong data-icon-type

Use a predefined key or custom

Did this answer your question?