Shopify Parallel Marquee – Infinite Scrolling Content Display
Add a dynamic scrolling marquee to your Shopify store with customizable content blocks for images, text, and logos. Features direction toggle between horizontal and vertical scrolling, reverse direction option, and elegant fade edges.
Liquid Code
<!-- ======================================== Section Name: Parallel Marquee Tech Stack: Liquid, HTML, CSS, JavaScript What This Section Does: - Displays an infinite scrolling marquee with customizable content blocks for images, text, and logos. - Features toggleable direction (horizontal/vertical) with smooth transitions. - Includes reverse direction option and masked fade edges for elegant presentation. - Fully responsive with customizable speeds, colors, and spacing. Promotion: Enhance your Shopify store with a versatile, attention-grabbing marquee section. Perfect for showcasing partners, testimonials, or featured content. Get it now at [PrebuiltTemplates](https://prebuilttemplates.com/). ======================================== --> {% comment %} Section: Parallel Marquee - Horizontal infinite scroll marquee with fade edges - Customizable content via blocks - Direction toggle option (horizontal/vertical) - Fully responsive with custom speeds {% endcomment %} <section class="marquee-section" style="--color-bg: {{ section.settings.background_color }}; --color-text: {{ section.settings.text_color }}; --color-bg-accent: {{ section.settings.accent_color }}; --duration: {{ section.settings.scroll_speed }}s;"> {% if section.settings.show_toggle %} <button class="toggle" id="direction-toggle-{{ section.id }}"> <span>{{ section.settings.toggle_text }}</span> <svg aria-hidden="true" viewBox="0 0 512 512" width="100" title="arrows-alt-h"> <path d="M377.941 169.941V216H134.059v-46.059c0-21.382-25.851-32.09-40.971-16.971L7.029 239.029c-9.373 9.373-9.373 24.568 0 33.941l86.059 86.059c15.119 15.119 40.971 4.411 40.971-16.971V296h243.882v46.059c0 21.382 25.851 32.09 40.971 16.971l86.059-86.059c9.373-9.373 9.373-24.568 0-33.941l-86.059-86.059c-15.119-15.12-40.971-4.412-40.971 16.97z" /> </svg> </button> {% endif %} <div class="wrapper" id="wrapper-{{ section.id }}"> <div class="marquee"> <div class="marquee__group"> {% for block in section.blocks %} {% if block.type == 'image_item' %} <div class="marquee-item" {{ block.shopify_attributes }}> {% if block.settings.image != blank %} {{ block.settings.image | image_url: width: 400 | image_tag: loading: 'lazy', class: 'marquee-image' }} {% else %} {{ 'image' | placeholder_svg_tag: 'marquee-image placeholder' }} {% endif %} {% if block.settings.caption != blank %} <div class="marquee-caption">{{ block.settings.caption }}</div> {% endif %} </div> {% elsif block.type == 'text_item' %} <div class="marquee-item marquee-text" {{ block.shopify_attributes }}> <div class="marquee-text-content"> {{ block.settings.text }} </div> </div> {% elsif block.type == 'logo_item' %} <div class="marquee-item marquee-logo" {{ block.shopify_attributes }}> {% if block.settings.logo != blank %} {{ block.settings.logo | image_url: width: 200 | image_tag: loading: 'lazy', class: 'marquee-logo-image' }} {% else %} {{ 'logo' | placeholder_svg_tag: 'marquee-logo-image placeholder' }} {% endif %} </div> {% endif %} {% endfor %} </div> <!-- Duplicate for infinite scroll --> <div class="marquee__group" aria-hidden="true"> {% for block in section.blocks %} {% if block.type == 'image_item' %} <div class="marquee-item"> {% if block.settings.image != blank %} {{ block.settings.image | image_url: width: 400 | image_tag: loading: 'lazy', class: 'marquee-image' }} {% else %} {{ 'image' | placeholder_svg_tag: 'marquee-image placeholder' }} {% endif %} {% if block.settings.caption != blank %} <div class="marquee-caption">{{ block.settings.caption }}</div> {% endif %} </div> {% elsif block.type == 'text_item' %} <div class="marquee-item marquee-text"> <div class="marquee-text-content"> {{ block.settings.text }} </div> </div> {% elsif block.type == 'logo_item' %} <div class="marquee-item marquee-logo"> {% if block.settings.logo != blank %} {{ block.settings.logo | image_url: width: 200 | image_tag: loading: 'lazy', class: 'marquee-logo-image' }} {% else %} {{ 'logo' | placeholder_svg_tag: 'marquee-logo-image placeholder' }} {% endif %} </div> {% endif %} {% endfor %} </div> </div> {% if section.settings.show_reverse %} <div class="marquee marquee--reverse"> <div class="marquee__group"> {% for block in section.blocks reversed %} {% if block.type == 'image_item' %} <div class="marquee-item" {{ block.shopify_attributes }}> {% if block.settings.image != blank %} {{ block.settings.image | image_url: width: 400 | image_tag: loading: 'lazy', class: 'marquee-image' }} {% else %} {{ 'image' | placeholder_svg_tag: 'marquee-image placeholder' }} {% endif %} {% if block.settings.caption != blank %} <div class="marquee-caption">{{ block.settings.caption }}</div> {% endif %} </div> {% elsif block.type == 'text_item' %} <div class="marquee-item marquee-text" {{ block.shopify_attributes }}> <div class="marquee-text-content"> {{ block.settings.text }} </div> </div> {% elsif block.type == 'logo_item' %} <div class="marquee-item marquee-logo" {{ block.shopify_attributes }}> {% if block.settings.logo != blank %} {{ block.settings.logo | image_url: width: 200 | image_tag: loading: 'lazy', class: 'marquee-logo-image' }} {% else %} {{ 'logo' | placeholder_svg_tag: 'marquee-logo-image placeholder' }} {% endif %} </div> {% endif %} {% endfor %} </div> <!-- Duplicate for infinite scroll --> <div class="marquee__group" aria-hidden="true"> {% for block in section.blocks reversed %} {% if block.type == 'image_item' %} <div class="marquee-item"> {% if block.settings.image != blank %} {{ block.settings.image | image_url: width: 400 | image_tag: loading: 'lazy', class: 'marquee-image' }} {% else %} {{ 'image' | placeholder_svg_tag: 'marquee-image placeholder' }} {% endif %} {% if block.settings.caption != blank %} <div class="marquee-caption">{{ block.settings.caption }}</div> {% endif %} </div> {% elsif block.type == 'text_item' %} <div class="marquee-item marquee-text"> <div class="marquee-text-content"> {{ block.settings.text }} </div> </div> {% elsif block.type == 'logo_item' %} <div class="marquee-item marquee-logo"> {% if block.settings.logo != blank %} {{ block.settings.logo | image_url: width: 200 | image_tag: loading: 'lazy', class: 'marquee-logo-image' }} {% else %} {{ 'logo' | placeholder_svg_tag: 'marquee-logo-image placeholder' }} {% endif %} </div> {% endif %} {% endfor %} </div> </div> {% endif %} </div> </section> <style> .marquee-section { --size: clamp(10rem, 1rem + 40vmin, 30rem); --gap: calc(var(--size) / 14); --scroll-start: 0; --scroll-end: calc(-100% - var(--gap)); box-sizing: border-box; overflow: hidden; padding: {{ section.settings.padding }}px 0; width: 100%; color: var(--color-text); background-color: var(--color-bg); } .marquee-section * { box-sizing: border-box; } .toggle { --size: 3rem; position: relative; position: fixed; top: 1rem; left: 1rem; width: var(--size); height: var(--size); font: inherit; text-align: center; cursor: pointer; outline: none; border: none; border-radius: 50%; color: inherit; background-color: var(--color-bg-accent); z-index: 5; } .toggle:focus-visible { box-shadow: 0 0 0 2px var(--color-text); } .toggle span { position: absolute; display: inline-block; top: 50%; left: calc(100% + 0.4em); width: fit-content; white-space: nowrap; transform: translateY(-50%); animation: fade 400ms 4s ease-out forwards; user-select: none; } .toggle svg { --size: 1.5rem; position: absolute; top: 50%; left: 50%; width: var(--size); height: var(--size); fill: currentcolor; transform: translate(-50%, -50%); transition: transform 300ms cubic-bezier(0.25, 1, 0.5, 1); } .toggle--vertical svg { transform: translate(-50%, -50%) rotate(-90deg); } .wrapper { display: flex; flex-direction: column; gap: var(--gap); margin: auto; max-width: 100vw; } .wrapper--vertical { flex-direction: row; height: 100vh; } .marquee { display: flex; overflow: hidden; user-select: none; gap: var(--gap); mask-image: linear-gradient( var(--mask-direction, to right), hsl(0 0% 0% / 0), hsl(0 0% 0% / 1) 20%, hsl(0 0% 0% / 1) 80%, hsl(0 0% 0% / 0) ); } .marquee__group { flex-shrink: 0; display: flex; align-items: center; justify-content: space-around; gap: var(--gap); min-width: 100%; animation: scroll-x var(--duration) linear infinite; } @media (prefers-reduced-motion: reduce) { .marquee__group { animation-play-state: paused; } } .marquee--vertical { --mask-direction: to bottom; } .marquee--vertical, .marquee--vertical .marquee__group { flex-direction: column; } .marquee--vertical .marquee__group { animation-name: scroll-y; } .marquee--reverse .marquee__group { animation-direction: reverse; animation-delay: calc(-1 * var(--duration) / 2); } @keyframes scroll-x { from { transform: translateX(var(--scroll-start)); } to { transform: translateX(var(--scroll-end)); } } @keyframes scroll-y { from { transform: translateY(var(--scroll-start)); } to { transform: translateY(var(--scroll-end)); } } @keyframes fade { to { opacity: 0; visibility: hidden; } } /* Item Styles */ .marquee-item { flex-shrink: 0; display: flex; justify-content: center; align-items: center; background: var(--color-bg-accent); border-radius: 0.5rem; padding: 20px; max-width: 300px; } .marquee-image { max-width: 100%; height: auto; border-radius: 0.25rem; } .marquee-caption { text-align: center; margin-top: 10px; font-size: 14px; } .marquee-text { padding: 20px; max-width: 300px; } .marquee-text-content { text-align: center; font-weight: 500; } .marquee-logo { padding: 15px; background: var(--color-bg-accent); } .marquee-logo-image { max-width: 100%; height: auto; max-height: 80px; } /* Vertical styling adjustments */ .marquee--vertical .marquee-item { width: calc(var(--size) / 1.5); aspect-ratio: 1; } </style> <script> document.addEventListener('DOMContentLoaded', function() { const sectionId = "{{ section.id }}"; const control = document.getElementById(`direction-toggle-${sectionId}`); if (control) { const marquees = document.querySelectorAll(`#wrapper-${sectionId} .marquee`); const wrapper = document.querySelector(`#wrapper-${sectionId}`); control.addEventListener("click", () => { control.classList.toggle("toggle--vertical"); wrapper.classList.toggle("wrapper--vertical"); marquees.forEach(marquee => marquee.classList.toggle("marquee--vertical") ); }); } }); </script> {% schema %} { "name": "Parallel Marquee", "tag": "section", "class": "section", "settings": [ { "type": "header", "content": "Marquee Colors" }, { "type": "color", "id": "background_color", "label": "Background Color", "default": "#f8f6f3" }, { "type": "color", "id": "text_color", "label": "Text Color", "default": "#333333" }, { "type": "color", "id": "accent_color", "label": "Accent Color", "default": "#ecdcc0" }, { "type": "header", "content": "Marquee Settings" }, { "type": "range", "id": "scroll_speed", "min": 20, "max": 120, "step": 5, "unit": "s", "label": "Scroll Speed", "default": 60 }, { "type": "range", "id": "padding", "min": 0, "max": 100, "step": 10, "unit": "px", "label": "Section Padding", "default": 40 }, { "type": "checkbox", "id": "show_reverse", "label": "Show Reverse Direction Row", "default": true }, { "type": "header", "content": "Direction Toggle" }, { "type": "checkbox", "id": "show_toggle", "label": "Show Direction Toggle Button", "default": true }, { "type": "text", "id": "toggle_text", "label": "Toggle Button Text", "default": "Toggle direction" } ], "blocks": [ { "type": "image_item", "name": "Image Item", "settings": [ { "type": "image_picker", "id": "image", "label": "Image" }, { "type": "text", "id": "caption", "label": "Caption", "default": "Image caption" } ] }, { "type": "text_item", "name": "Text Item", "settings": [ { "type": "richtext", "id": "text", "label": "Text", "default": "<p>Your text here</p>" } ] }, { "type": "logo_item", "name": "Logo Item", "settings": [ { "type": "image_picker", "id": "logo", "label": "Logo" } ] } ], "presets": [ { "name": "Parallel Marquee", "blocks": [ { "type": "logo_item" }, { "type": "logo_item" }, { "type": "logo_item" }, { "type": "logo_item" }, { "type": "logo_item" }, { "type": "logo_item" } ] } ] } {% endschema %}