"Add To Wishlist Button" Snippet v2
Read this article to learn more about the snippet usage.
Usage:
{% render 'wl-add-button-v2' %}
Code:
{% comment %}
wl-add-button-v2
Heart button that adds or removes a product from the wishlist.
Requires
- Wishlist app installed
- App embeds → Wishlist helper enabled (handles clicks; no JS in this file)
Styles ship inside this snippet, so the button looks correct even if the
helper is off — but clicks will not work without the helper.
Setup
1. Online Store → Themes → Edit code → Snippets → Add a new snippet.
2. Name it wl-add-button-v2 and paste this file.
3. Render it on the product page or inside a product card.
Examples
Product page (tracks the selected variant):
{% render 'wl-add-button-v2' %}
Collection / search / product card (always pass the card product):
{% render 'wl-add-button-v2', wish_product: card_product, button_position: 'absolute' %}
Logged-in customers only:
{% render 'wl-add-button-v2', wish_product: card_product, visibility: 'logged_in_only' %}
Parameters
wish_product Product for cards. Omit on the product page (uses `product`).
visibility everyone (default) | logged_in_only
view icon_only (default) | icon_and_text | text_only
button_position static (default) | absolute
content_align left | center | right (default)
show_popup Toast after add/remove. Default: true
icon_color Default: #000000
icon_size Desktop icon size, px. Default: 20
icon_size_mobile Mobile icon size, px. Default: 20
text_color Default: #000000
text_size Desktop label size, px. Default: 14
text_size_mobile Mobile label size, px. Default: 14
icon_text_gap Gap between icon and label, px. Default: 6
margin_top px. Default: 0
margin_right px. Default: 0
margin_bottom px. Default: 0
margin_left px. Default: 0
max_width px. 0 = no limit. Default: 0
button_border Show border. Default: false
button_border_color Default: #000000
button_border_width px. Default: 1
button_border_radius px. Default: 0
button_padding_x px. Default: 0
button_padding_y px. Default: 0
Notes
- Labels use theme translations (English fallback if missing):
wishlist.add_to_wishlist
wishlist.remove
{% endcomment %}
{% liquid
assign is_blocked = shop.metafields.wishlist.app_blocked
assign product = wish_product | default: product
assign visibility = visibility | default: 'everyone'
assign show_snippet = true
unless request.design_mode or customer
if visibility == 'logged_in_only'
assign show_snippet = false
endif
endunless
assign view = view | default: 'icon_only'
assign button_position = button_position | default: 'static'
assign content_align = content_align | default: 'right'
assign show_popup = show_popup | default: true
assign icon_color = icon_color | default: '#000000'
assign icon_size = icon_size | default: 20
assign icon_size_mobile = icon_size_mobile | default: 20
assign text_color = text_color | default: '#000000'
assign text_size = text_size | default: 14
assign text_size_mobile = text_size_mobile | default: 14
assign icon_text_gap = icon_text_gap | default: 6
assign margin_top = margin_top | default: 0
assign margin_right = margin_right | default: 0
assign margin_bottom = margin_bottom | default: 0
assign margin_left = margin_left | default: 0
assign max_width = max_width | default: 0
assign button_border = button_border | default: false
assign button_border_color = button_border_color | default: '#000000'
assign button_border_width = button_border_width | default: 1
assign button_border_radius = button_border_radius | default: 0
assign button_padding_x = button_padding_x | default: 0
assign button_padding_y = button_padding_y | default: 0
assign show_icon = true
assign show_text = false
if view == 'icon_and_text'
assign show_text = true
elsif view == 'text_only'
assign show_icon = false
assign show_text = true
endif
assign align_class = 'wl-add--align-right'
if content_align == 'left'
assign align_class = 'wl-add--align-left'
elsif content_align == 'center'
assign align_class = 'wl-add--align-center'
endif
assign locale_code = request.locale.iso_code | split: '-' | first | strip
assign dir_value = 'ltr'
if locale_code == 'ar' or locale_code == 'he' or locale_code == 'fa' or locale_code == 'ur'
assign dir_value = 'rtl'
endif
assign initial_variant = product.selected_or_first_available_variant
assign product_image = product.featured_image | default: initial_variant.image
assign text_add = 'wishlist.add_to_wishlist' | t
if text_add == 'wishlist.add_to_wishlist'
assign text_add = 'Add to wishlist'
endif
assign text_remove = 'wishlist.remove' | t
if text_remove == 'wishlist.remove'
assign text_remove = 'Remove from wishlist'
endif
%}
{% unless is_blocked or product == blank or show_snippet == false %}
<style>
wishlist-add-button:not(:defined) {
visibility: visible !important;
}
.wl-add {
--wl-add-margin-top: 0;
--wl-add-margin-right: 0;
--wl-add-margin-bottom: 0;
--wl-add-margin-left: 0;
--wl-add-max-width: none;
--wl-add-position: static;
--wl-add-z-index: 100;
--wl-icon-label-gap: 8px;
--wl-icon-label-font-size: 14px;
--wl-icon-label-font-size-md: 16px;
--wl-icon-label-text-color: currentColor;
--wl-icon-label-icon-color: currentColor;
--wl-icon-label-icon-size: 18px;
--wl-icon-label-icon-size-md: 20px;
display: flex;
position: var(--wl-add-position);
z-index: var(--wl-add-z-index);
margin: 0;
width: 100%;
max-width: var(--wl-add-max-width);
user-select: none;
}
.wl-add--align-left {
justify-content: flex-start;
}
.wl-add--align-center {
justify-content: center;
}
.wl-add--align-right {
justify-content: flex-end;
}
.wl-add__trigger {
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
margin: var(--wl-add-margin-top) var(--wl-add-margin-right)
var(--wl-add-margin-bottom) var(--wl-add-margin-left);
width: auto;
}
.wl-add .wl-add__trigger:not(.wl-fab) {
border: none;
background: none;
padding: 0;
}
.wl-add--snippet .wl-add__trigger:not(.wl-fab) {
gap: var(--wl-icon-label-gap, 6px);
border: var(--wl-add-btn-border, none);
border-radius: var(--wl-add-btn-radius, 0);
background: none;
padding: var(--wl-add-btn-padding, 0);
color: inherit;
font: inherit;
}
.wl-add .wl-icon-label {
display: inline-flex;
flex-wrap: nowrap;
align-items: center;
gap: var(--wl-icon-label-gap);
color: var(--wl-icon-label-text-color);
font-size: var(--wl-icon-label-font-size);
line-height: 1.2;
}
@media screen and (min-width: 768px) {
.wl-add .wl-icon-label {
font-size: var(--wl-icon-label-font-size-md);
}
}
.wl-add .wl-icon-label__media {
display: inline-flex;
flex-shrink: 0;
justify-content: center;
align-items: center;
width: var(--wl-icon-label-icon-size);
height: var(--wl-icon-label-icon-size);
color: var(--wl-icon-label-icon-color);
}
@media screen and (min-width: 768px) {
.wl-add .wl-icon-label__media {
width: var(--wl-icon-label-icon-size-md);
height: var(--wl-icon-label-icon-size-md);
}
}
.wl-add .wl-icon-label__media svg,
.wl-add .wl-icon-label__icon svg {
width: 100%;
height: 100%;
object-fit: contain;
}
.wl-add .wl-icon-label__icon {
display: block;
width: 100%;
height: 100%;
}
.wl-add .wl-icon-label__icon--filled {
display: none;
}
.wl-add.wl-add--active .wl-icon-label__media .icon-heart {
fill: currentColor;
}
.wl-add.wl-add--active .wl-icon-label__icon--empty {
display: none;
}
.wl-add.wl-add--active .wl-icon-label__icon--filled {
display: block;
}
.wl-add .wl-icon-label__label {
min-width: 0;
text-align: inherit;
}
</style>
<wishlist-add-button
class='wl-add wl-add--snippet {{ align_class }}'
data-wl-product-id='{{ product.id }}'
data-wl-variant-id='{{ initial_variant.id }}'
data-wl-handle='{{ product.handle | escape }}'
data-wl-product-title='{{ product.title | escape }}'
{% if product_image != blank %}
data-wl-product-image='{{ product_image | image_url: width: 120 }}'
{% endif %}
{% unless show_popup %}
data-wl-skip-notification='true'
{% endunless %}
dir='{{ dir_value }}'
style='
--wl-add-position: {{ button_position }};
--wl-icon-label-icon-color: {{ icon_color }};
--wl-icon-label-icon-size: {{ icon_size_mobile }}px;
--wl-icon-label-icon-size-md: {{ icon_size }}px;
--wl-icon-label-text-color: {{ text_color }};
--wl-icon-label-font-size: {{ text_size_mobile }}px;
--wl-icon-label-font-size-md: {{ text_size }}px;
--wl-icon-label-gap: {{ icon_text_gap }}px;
--wl-add-margin-top: {{ margin_top }}px;
--wl-add-margin-right: {{ margin_right }}px;
--wl-add-margin-bottom: {{ margin_bottom }}px;
--wl-add-margin-left: {{ margin_left }}px;
--wl-add-btn-padding: {{ button_padding_y }}px {{ button_padding_x }}px;
{% if max_width > 0 %}--wl-add-max-width: {{ max_width }}px;{% endif %}
{% if button_border %}--wl-add-btn-border: {{ button_border_width }}px solid {{ button_border_color }}; --wl-add-btn-radius: {{ button_border_radius }}px;{% endif %}
'
>
<button
type='button'
class='wl-add__trigger'
aria-pressed='false'
aria-label='{{ text_add | escape }}'
data-wl-label-add='{{ text_add | escape }}'
data-wl-label-remove='{{ text_remove | escape }}'
data-wl-trigger
>
<span class='wl-icon-label' dir='{{ dir_value }}'>
{% if show_icon %}
<span class='wl-icon-label__media' aria-hidden='true'>
<span class='wl-icon-label__icon wl-icon-label__icon--empty'>
<svg
class='icon-heart'
xmlns='http://www.w3.org/2000/svg'
fill='none'
viewBox='0 0 24 24'
aria-hidden='true'
focusable='false'
>
<path
stroke='currentColor'
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='1.5'
d='M7.87891 3.75c.67013.00152 1.33423.14051 1.9541.40918.61989.26872 1.18439.66253 1.66019 1.16016.1399.14633.3336.22972.5361.23144.2024.00163.3967-.07878.5391-.22266.9658-.9764 2.2584-1.51357 3.5957-1.50488 1.3372.00873 2.6231.5627 3.5771 1.55176.955.98998 1.5 2.33576 1.5088 3.74707.0087 1.41133-.52 2.76473-1.4629 3.76753l-6.6318 6.877c-.3018.3128-.7055.4834-1.1201.4834-.4146-.0001-.8175-.1707-1.1192-.4834l-6.63963-6.8828-.00196-.0029-.17578-.1885c-.3984-.452-.71987-.9742-.94922-1.543-.26198-.6498-.39789-1.34784-.39941-2.0537-.0015-.70608.13124-1.40537.39062-2.05664.25939-.6512.64026-1.24084 1.11817-1.73633.47787-.49543 1.04403-.88648 1.66504-1.15234.62086-.26578 1.28506-.40188 1.95508-.40039'
/>
</svg>
</span>
<span class='wl-icon-label__icon wl-icon-label__icon--filled'>
<svg
class='icon-heart'
xmlns='http://www.w3.org/2000/svg'
fill='currentColor'
viewBox='0 0 24 24'
aria-hidden='true'
focusable='false'
>
<path
stroke='currentColor'
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='1.5'
d='M7.87891 3.75c.67013.00152 1.33423.14051 1.9541.40918.61989.26872 1.18439.66253 1.66019 1.16016.1399.14633.3336.22972.5361.23144.2024.00163.3967-.07878.5391-.22266.9658-.9764 2.2584-1.51357 3.5957-1.50488 1.3372.00873 2.6231.5627 3.5771 1.55176.955.98998 1.5 2.33576 1.5088 3.74707.0087 1.41133-.52 2.76473-1.4629 3.76753l-6.6318 6.877c-.3018.3128-.7055.4834-1.1201.4834-.4146-.0001-.8175-.1707-1.1192-.4834l-6.63963-6.8828-.00196-.0029-.17578-.1885c-.3984-.452-.71987-.9742-.94922-1.543-.26198-.6498-.39789-1.34784-.39941-2.0537-.0015-.70608.13124-1.40537.39062-2.05664.25939-.6512.64026-1.24084 1.11817-1.73633.47787-.49543 1.04403-.88648 1.66504-1.15234.62086-.26578 1.28506-.40188 1.95508-.40039'
/>
</svg>
</span>
</span>
{% endif %}
{% if show_text %}
<span class='wl-icon-label__label' data-wl-icon-label-text>
{{- text_add | escape -}}
</span>
{% endif %}
</span>
</button>
</wishlist-add-button>
{% endunless %}