Production Shopify · Campaign sliders

Ship campaign sliders with merchant-editable slides

Seasonal campaigns, lookbook showcases, and rotating promos need carousels where merchants swap slides, update CTAs, and retire old creative—without developer intervention. This guide is about slider sections that treat slide images as the primary editable object and respect motion accessibility.

Production implementation guide · Updated 2026-08-03

Sliders are not flat hero settings—teach the block model

A homepage hero often has one image, one heading, one CTA—stored in section.settings. A campaign slider needs 3–8 slides, each with its own image, optional text overlay, and destination URL. That is a block collection, not flat settings.

Hero sections

  • Single image, heading, CTA in section.settings
  • No reordering—content is one complete unit
  • Good for above-the-fold campaign landing
  • No motion system required

Slider sections

  • Multiple image slides in blocks
  • Merchants drag to reorder, disable, or add slides
  • Good for showcasing multiple products or stories
  • Requires motion controls and autoplay pause

Slide images as the primary editable object

Each slide block should have an image picker as the primary setting, with optional heading, subheading, button label, and button URL. The image is required; text overlays are optional enhancements. This teaches merchants that sliders are image-first.

Set default slide images in the preset. Empty image states should render a placeholder in the editor, not a broken layout.

Schema sketch — slide blocks with image primary

{
  "name': 'Campaign slider",
  "settings": [
    {
      "type': 'checkbox",
      "id': 'autoplay",
      "label': 'Autoplay slides",
      "default": false
    },
    {
      "type': 'range",
      "id': 'autoplay_speed",
      "label': 'Autoplay speed (seconds)",
      "min": 3,
      "max": 10,
      "step": 1,
      "default": 5
    }
  ],
  "blocks": [
    {
      "type': 'slide",
      "name': 'Slide",
      "settings": [
        {
          "type': 'image_picker",
          "id': 'image",
          "label': 'Slide image"
        },
        {
          "type': 'text",
          "id': 'heading",
          "label': 'Heading (optional)"
        },
        {
          "type': 'text",
          "id': 'button_label",
          "label': 'Button label (optional)"
        },
        {
          "type': 'url",
          "id': 'button_url",
          "label': 'Button URL"
        }
      ]
    }
  ],
  "max_blocks": 8,
  "presets": [
    {
      "name': 'Campaign slider",
      "blocks": [
        { "type": "slide" },
        { "type": "slide" },
        { "type": "slide" }
      ]
    }
  ]
}

Image picker first in settings order. Optional text overlay fields. Three-slide preset demonstrates the pattern.

Set max_blocks to prevent carousel overload

Most campaign sliders should have 4–8 slides. More than that, and autoplay becomes unusable, load time suffers, and the carousel never completes a rotation. Set max_blocks in schema to enforce this constraint.

If a merchant truly needs 20+ slides, that is a different pattern (infinite scroll gallery or paginated grid)—not an autoplay carousel.

Lazy load off-screen slide images

Only the first slide image should load eagerly (loading=eager or fetchpriority=high if it is LCP). All other slides should use loading=lazy. This prevents wasting bandwidth on images the visitor may never see.

Combine with height reservation to prevent layout shift when lazy slides load.

Lazy loading sketch for slides

{% for block in section.blocks %}
  {% assign is_first = forloop.first %}
  <div class="slider__slide" {{ block.shopify_attributes }}>
    {% if block.settings.image %}
      {{
        block.settings.image
        | image_url: width: 1920
        | image_tag:
          loading: is_first ? 'eager' : 'lazy',
          widths: '375, 750, 1100, 1500, 1920',
          class: 'slider__image'
      }}
    {% endif %}
    {% if block.settings.heading %}
      <h2 class="slider__heading">{{ block.settings.heading | escape }}</h2>
    {% endif %}
  </div>
{% endfor %}

First slide eager, rest lazy. Liquid 2.0 image_tag filter handles srcset and sizes automatically.

Pause autoplay for prefers-reduced-motion

Users with vestibular disorders or motion sensitivity enable prefers-reduced-motion. Sliders must respect this: disable autoplay, remove transitions, or switch to a static gallery. This is a WCAG requirement.

Provide a manual pause button regardless of reduced-motion preference. Auto-playing carousels without pause controls fail accessibility audits.

Reduced motion detection sketch

const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

if (section.settings.autoplay && !prefersReducedMotion) {
  startAutoplay();
} else {
  // Manual navigation only
}

// Also provide a pause button for users without reduced-motion preference
pauseButton.addEventListener('click', () => {
  stopAutoplay();
  pauseButton.setAttribute('aria-label', 'Play slides');
});

Check media query before starting autoplay. Always provide manual pause control.

Per-slide CTA URLs: link the image or use a button

Each slide can have a unique destination. Two patterns: wrap the entire slide in an <a> with the image and optional text, or render a button overlay. Wrapping is simpler but limits text selecatability. Buttons are more flexible but require hover/tap target sizing.

If a slide has no URL, do not render a broken link or disabled button—just show the image.

Production debugging for slider sections

Slider section symptoms and checks
SymptomChecks
Autoplay never startsprefers-reduced-motion active? JS error before init? Slide count < 2?
Layout shift when slides changeImage height reserved? Lazy images cause reflow? Container height unset?
First slide not LCP candidateloading=lazy on first image? Image above fold but not prioritized?
Dots/controls not synced with active slideAria-current updated? Active class on wrong slide? ID mismatch?

Practice a campaign slider section by hand

Build this on a development index template before using any generator. You should explain slide blocks, lazy loading, and reduced-motion pause.

  1. 01

    Create sections/campaign-slider.liquid

    Implement slide blocks with image primary, max_blocks, autoplay setting.

  2. 02

    Lazy loading logic

    First slide eager, rest lazy. Reserve height to prevent shift.

  3. 03

    Reduced-motion check

    Disable autoplay if prefers-reduced-motion. Always provide pause button.

  4. 04

    Per-slide CTAs

    Link image or render button if URL present; hide CTA if empty.

  5. 05

    Mobile and duplication test

    Touch swipe works. Duplicate section on template; both operate independently.

Use the converter after the slider model is settled

Static carousel HTML can be drafted faster in the converter once you know whether you need autoplay, per-slide CTAs, and lazy loading strategy. The converter does not decide motion systems for you.

Supporting draft acceleration — not a substitute for slider UX design.

What to study next for campaign slider sections

Continue with adjacent skills. Hero sections are a different pattern—study when a single static image is better than a carousel.

Beginner

Liquid and image filters before motion systems.

Intermediate

Blocks, accessibility, and related motion UI.

Advanced

Delivery under merchandising pressure.

Editorial review

Reviewed by the HTML to Liquid Converter team

Dhruv Goyani, Shopify Developer at HTML to Liquid Converter

Dhruv Goyani

3 years web design + 3 years Shopify development experience

LinkedIn profile →
Nishad Kikani, Lead Shopify Developer at HTML to Liquid Converter

Nishad Kikani

2 years web design + 6 years Shopify development experience

LinkedIn profile →

Content is reviewed by the HTML to Liquid Converter Shopify development team before publication. Technical accuracy is validated against current Shopify Online Store 2.0 conventions and active client theme work.

Last updated:

Questions or corrections? Contact us.