Shopify Snippet Library

SKILL.md

Shopify Snippet Library

Snippet Documentation Format

All snippets should include documentation using Liquid comments:

{% comment %}
  Snippet: [Name]
  Description: [What this snippet does]

  Parameters:
  - param_name {type} - Description [required/optional]

  Usage:
  {% render 'snippet-name', param_name: value %}

  Example:
  {% render 'product-card', product: product, show_vendor: true %}
{% endcomment %}

Common Snippet Patterns

1. Product Card

{% comment %}
  Snippet: Product Card
  Description: Displays a product with image, title, vendor, and price

  Parameters:
  - product {product} - The product object [required]
  - show_vendor {boolean} - Show product vendor (default: false) [optional]
  - image_size {number} - Image width in pixels (default: 400) [optional]
  - class {string} - Additional CSS classes [optional]

  Usage:
  {% render 'product-card', product: product, show_vendor: true, image_size: 600 %}
{% endcomment %}

{%- liquid
  assign show_vendor = show_vendor | default: false
  assign image_size = image_size | default: 400
-%}

{%- if product == blank -%}
  <div class="product-card product-card--empty {{ class }}">
    <p>Product not available</p>
  </div>
{%- else -%}
  <article class="product-card {{ class }}">
    <a href="{{ product.url }}" class="product-card__link">
      {%- if product.featured_image -%}
        <div class="product-card__image">
          <img
            src="{{ product.featured_image | image_url: width: image_size }}"
            alt="{{ product.featured_image.alt | escape }}"
            loading="lazy"
            width="{{ image_size }}"
            height="{{ image_size | divided_by: product.featured_image.aspect_ratio | ceil }}"
          >
        </div>
      {%- endif -%}

      <div class="product-card__info">
        {%- if show_vendor and product.vendor != blank -%}
          <p class="product-card__vendor">{{ product.vendor | escape }}</p>
        {%- endif -%}

        <h3 class="product-card__title">{{ product.title | escape }}</h3>

        <div class="product-card__price">
          {%- if product.compare_at_price > product.price -%}
            <span class="product-card__price--sale">{{ product.price | money }}</span>
            <span class="product-card__price--compare">{{ product.compare_at_price | money }}</span>
          {%- else -%}
            <span>{{ product.price | money }}</span>
          {%- endif -%}
        </div>
      </div>
    </a>
  </article>
{%- endif -%}

2. Button / Link

{% comment %}
  Snippet: Button
  Description: Renders a customizable button or link

  Parameters:
  - text {string} - Button text [required]
  - url {string} - Button URL (makes it a link) [optional]
  - style {string} - Button style: 'primary', 'secondary', 'outline' (default: 'primary') [optional]
  - size {string} - Button size: 'small', 'medium', 'large' (default: 'medium') [optional]
  - class {string} - Additional CSS classes [optional]

  Usage:
  {% render 'button', text: 'Add to Cart', style: 'primary', size: 'large' %}
  {% render 'button', text: 'Learn More', url: '/pages/about', style: 'outline' %}
{% endcomment %}

{%- liquid
  assign style = style | default: 'primary'
  assign size = size | default: 'medium'
  assign btn_class = 'btn btn--' | append: style | append: ' btn--' | append: size
  if class
    assign btn_class = btn_class | append: ' ' | append: class
  endif
-%}

{%- if url != blank -%}
  <a href="{{ url }}" class="{{ btn_class }}">
    {{ text | escape }}
  </a>
{%- else -%}
  <button type="button" class="{{ btn_class }}">
    {{ text | escape }}
  </button>
{%- endif -%}

3. Icon (SVG)

{% comment %}
  Snippet: Icon
  Description: Renders an SVG icon

  Parameters:
  - name {string} - Icon name (e.g., 'cart', 'heart', 'search') [required]
  - size {number} - Icon size in pixels (default: 24) [optional]
  - class {string} - Additional CSS classes [optional]

  Usage:
  {% render 'icon', name: 'cart', size: 20, class: 'icon-primary' %}
{% endcomment %}

{%- liquid
  assign size = size | default: 24
  assign icon_class = 'icon icon-' | append: name
  if class
    assign icon_class = icon_class | append: ' ' | append: class
  endif
-%}

<svg class="{{ icon_class }}" width="{{ size }}" height="{{ size }}" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
  {%- case name -%}
    {%- when 'cart' -%}
      <path d="M9 2L8 4H4C2.9 4 2 4.9 2 6V18C2 19.1 2.9 20 4 20H20C21.1 20 22 19.1 22 18V6C22 4.9 21.1 4 20 4H16L15 2H9Z" stroke="currentColor" stroke-width="2"/>
    {%- when 'heart' -%}
      <path d="M20.84 4.61C19.91 3.68 18.69 3.17 17.42 3.17C16.15 3.17 14.93 3.68 14 4.61L12 6.61L10 4.61C9.07 3.68 7.85 3.17 6.58 3.17C5.31 3.17 4.09 3.68 3.16 4.61C1.22 6.55 1.22 9.69 3.16 11.63L12 20.47L20.84 11.63C22.78 9.69 22.78 6.55 20.84 4.61Z" stroke="currentColor" stroke-width="2"/>
    {%- when 'search' -%}
      <circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2"/>
      <path d="M21 21L16.65 16.65" stroke="currentColor" stroke-width="2"/>
    {%- when 'close' -%}
      <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2"/>
    {%- else -%}
      <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
  {%- endcase -%}
</svg>

4. Form Input

{% comment %}
  Snippet: Form Input
  Description: Renders a form input field with label

  Parameters:
  - type {string} - Input type (text, email, tel, number, etc.) [required]
  - name {string} - Input name attribute [required]
  - label {string} - Input label [required]
  - required {boolean} - Make field required (default: false) [optional]
  - placeholder {string} - Placeholder text [optional]
  - value {string} - Default value [optional]
  - class {string} - Additional CSS classes [optional]

  Usage:
  {% render 'form-input', type: 'email', name: 'email', label: 'Email Address', required: true %}
{% endcomment %}

{%- liquid
  assign required = required | default: false
  assign input_id = 'input-' | append: name
-%}

<div class="form-field {{ class }}">
  <label for="{{ input_id }}" class="form-field__label">
    {{ label | escape }}
    {%- if required -%}
      <span class="form-field__required" aria-label="required">*</span>
    {%- endif -%}
  </label>

  <input
    type="{{ type }}"
    id="{{ input_id }}"
    name="{{ name }}"
    class="form-field__input"
    {%- if placeholder -%}placeholder="{{ placeholder | escape }}"{%- endif -%}
    {%- if value -%}value="{{ value | escape }}"{%- endif -%}
    {%- if required -%}required{%- endif -%}
    {%- if type == 'email' -%}autocomplete="email"{%- endif -%}
  >
</div>

5. Image with Fallback

{% comment %}
  Snippet: Responsive Image
  Description: Renders a responsive image with fallback

  Parameters:
  - image {image} - The image object [required]
  - width {number} - Image width (default: 800) [optional]
  - height {number} - Image height [optional]
  - alt {string} - Alt text (uses image.alt if not provided) [optional]
  - class {string} - Additional CSS classes [optional]
  - loading {string} - Loading attribute: 'lazy' or 'eager' (default: 'lazy') [optional]

  Usage:
  {% render 'image', image: product.featured_image, width: 600, alt: product.title %}
{% endcomment %}

{%- liquid
  assign width = width | default: 800
  assign loading = loading | default: 'lazy'
  assign alt_text = alt | default: image.alt
-%}

{%- if image != blank -%}
  {%- if height -%}
    <img
      src="{{ image | image_url: width: width, height: height }}"
      alt="{{ alt_text | escape }}"
      width="{{ width }}"
      height="{{ height }}"
      loading="{{ loading }}"
      class="{{ class }}"
    >
  {%- else -%}
    <img
      srcset="
        {{ image | image_url: width: 400 }} 400w,
        {{ image | image_url: width: 800 }} 800w,
        {{ image | image_url: width: 1200 }} 1200w
      "
      sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw"
      src="{{ image | image_url: width: width }}"
      alt="{{ alt_text | escape }}"
      width="{{ width }}"
      height="{{ width | divided_by: image.aspect_ratio | ceil }}"
      loading="{{ loading }}"
      class="{{ class }}"
    >
  {%- endif -%}
{%- else -%}
  <div class="image-placeholder {{ class }}" role="img" aria-label="No image available"></div>
{%- endif -%}

6. Price Display

{% comment %}
  Snippet: Price
  Description: Displays product price with sale indication

  Parameters:
  - product {product} - The product object [required]
  - show_compare {boolean} - Show compare at price (default: true) [optional]
  - class {string} - Additional CSS classes [optional]

  Usage:
  {% render 'price', product: product %}
  {% render 'price', product: product, show_compare: false %}
{% endcomment %}

{%- liquid
  assign show_compare = show_compare | default: true
  assign on_sale = false
  if product.compare_at_price > product.price
    assign on_sale = true
  endif
-%}

<div class="price {{ class }}{% if on_sale %} price--on-sale{% endif %}">
  {%- if on_sale -%}
    <span class="price__sale">{{ product.price | money }}</span>
    {%- if show_compare -%}
      <span class="price__compare">{{ product.compare_at_price | money }}</span>
    {%- endif -%}
  {%- else -%}
    <span class="price__regular">{{ product.price | money }}</span>
  {%- endif -%}
</div>

7. Badge / Tag

{% comment %}
  Snippet: Badge
  Description: Displays a badge or tag

  Parameters:
  - text {string} - Badge text [required]
  - style {string} - Badge style: 'sale', 'new', 'featured', 'default' (default: 'default') [optional]
  - class {string} - Additional CSS classes [optional]

  Usage:
  {% render 'badge', text: 'Sale', style: 'sale' %}
  {% render 'badge', text: 'New Arrival', style: 'new' %}
{% endcomment %}

{%- liquid
  assign style = style | default: 'default'
  assign badge_class = 'badge badge--' | append: style
  if class
    assign badge_class = badge_class | append: ' ' | append: class
  endif
-%}

{%- if text != blank -%}
  <span class="{{ badge_class }}">
    {{ text | escape }}
  </span>
{%- endif -%}

8. Loading Spinner

{% comment %}
  Snippet: Loading Spinner
  Description: Displays a loading spinner

  Parameters:
  - size {string} - Spinner size: 'small', 'medium', 'large' (default: 'medium') [optional]
  - class {string} - Additional CSS classes [optional]

  Usage:
  {% render 'loading-spinner', size: 'large' %}
{% endcomment %}

{%- liquid
  assign size = size | default: 'medium'
  assign spinner_class = 'spinner spinner--' | append: size
  if class
    assign spinner_class = spinner_class | append: ' ' | append: class
  endif
-%}

<div class="{{ spinner_class }}" role="status" aria-label="Loading">
  <svg class="spinner__svg" viewBox="0 0 50 50">
    <circle class="spinner__circle" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
  </svg>
  <span class="sr-only">Loading...</span>
</div>

Best Practices

1. Always Document Parameters

{% comment %}
  Parameters:
  - param {type} - Description [required/optional]
{% endcomment %}

2. Provide Defaults

{%- liquid
  assign show_vendor = show_vendor | default: false
  assign image_size = image_size | default: 400
-%}

3. Validate Required Parameters

{%- if product == blank -%}
  <p class="error">Product parameter is required</p>
  {%- return -%}
{%- endif -%}

4. Handle Empty States

{%- if image != blank -%}
  <!-- Image markup -->
{%- else -%}
  <div class="placeholder">No image available</div>
{%- endif -%}

5. Escape User-Provided Content

<h3>{{ product.title | escape }}</h3>
<p>{{ customer.name | escape }}</p>

6. Use Semantic HTML

<article>  {%- # For products -%}
<nav>      {%- # For navigation -%}
<aside>    {%- # For sidebars -%}
<section>  {%- # For content sections -%}

7. Include Accessibility Attributes

<button aria-label="Add {{ product.title | escape }} to cart">
  Add to Cart
</button>

<img src="..." alt="{{ image.alt | escape }}">

<div role="status" aria-live="polite">
  Item added to cart
</div>

Create well-documented, reusable snippets that are easy to understand and maintain.

Weekly Installs
0
GitHub Stars
1
First Seen
Jan 1, 1970