Free Logo Marquee Section for ShopifyNo app. Copy, paste, done.
- Online Store 2.0
- No app
- Theme Check: 0 errors
- MIT license
The Stackframes logo marquee is a free Shopify section that scrolls a row of brand or press logos across the page. It is built for "as seen in" and partner strips. The animation is pure CSS. It pauses on hover, keyboard focus or a pause button, and it turns into a static, wrapped row for shoppers who prefer reduced motion. No app is required.
Live preview with sample content. Once installed, fonts follow your theme and colours are editable in the theme editor.
{%- liquid
assign logo_count = section.blocks.size
-%}
{%- if logo_count > 0 or request.design_mode -%}
<sf-logo-marquee
class="sf-logos"
style="--sf-logos-bg: {{ section.settings.background_color }}; --sf-logos-text: {{ section.settings.text_color }}; --sf-logos-duration: {{ section.settings.duration }}s; --sf-logos-height: {{ section.settings.logo_height }}px; --sf-logos-pt: {{ section.settings.padding_top }}px; --sf-logos-pb: {{ section.settings.padding_bottom }}px;"
>
{%- if section.settings.heading != blank -%}
<p class="sf-logos__heading">{{ section.settings.heading | escape }}</p>
{%- endif -%}
{%- if logo_count > 0 -%}
<div class="sf-logos__viewport">
<div class="sf-logos__track">
{%- for copy in (1..2) -%}
<ul class="sf-logos__list" role="list" {% if copy == 2 %}aria-hidden="true"{% endif %}>
{%- for block in section.blocks -%}
<li class="sf-logos__item" {% if copy == 1 %}{{ block.shopify_attributes }}{% endif %}>
{%- capture logo_markup -%}
{%- if block.settings.logo != blank -%}
{%- assign logo_w = block.settings.logo.aspect_ratio | times: section.settings.logo_height | round -%}
{{ block.settings.logo | image_url: width: 480 | image_tag: width: logo_w, height: section.settings.logo_height, alt: block.settings.name, class: 'sf-logos__img' }}
{%- else -%}
<span class="sf-logos__wordmark">{{ block.settings.name | escape }}</span>
{%- endif -%}
{%- endcapture -%}
{%- if block.settings.link != blank and copy == 1 -%}
<a class="sf-logos__link" href="{{ block.settings.link }}">{{ logo_markup }}</a>
{%- else -%}
{{ logo_markup }}
{%- endif -%}
</li>
{%- endfor -%}
</ul>
{%- endfor -%}
</div>
</div>
<button type="button" class="sf-logos__toggle" aria-pressed="false" aria-label="Pause logo animation">
<svg class="sf-logos__icon-pause" aria-hidden="true" focusable="false" viewBox="0 0 20 20" width="20" height="20"><path d="M7 4.5v11M13 4.5v11" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<svg class="sf-logos__icon-play" aria-hidden="true" focusable="false" viewBox="0 0 20 20" width="20" height="20"><path d="M7 4.5v11l8.5-5.5z" fill="currentColor"/></svg>
</button>
{%- else -%}
<p class="sf-logos__empty">Add logo blocks to show the brands you work with.</p>
{%- endif -%}
</sf-logo-marquee>
{%- endif -%}
{% stylesheet %}
.sf-logos { display: block; position: relative; overflow: hidden; background: var(--sf-logos-bg); color: var(--sf-logos-text); padding: var(--sf-logos-pt) 0 var(--sf-logos-pb); }
.sf-logos__heading { margin: 0 0 20px; padding: 0 20px; text-align: center; font-size: 0.8125em; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.7; }
.sf-logos__viewport { overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.sf-logos__track { display: flex; width: max-content; animation: sf-logos-scroll var(--sf-logos-duration) linear infinite; }
.sf-logos__list { display: flex; align-items: center; gap: 56px; margin: 0; padding: 0 28px; list-style: none; flex: none; min-width: 100vw; justify-content: space-around; }
.sf-logos__item { flex: none; display: flex; align-items: center; height: var(--sf-logos-height); }
.sf-logos__img { display: block; width: auto; height: 100%; max-width: none; object-fit: contain; }
.sf-logos__wordmark { font-size: calc(var(--sf-logos-height) * 0.55); font-weight: 700; letter-spacing: -0.02em; line-height: 1; white-space: nowrap; opacity: 0.85; }
.sf-logos__link { display: flex; align-items: center; height: 100%; color: inherit; text-decoration: none; }
.sf-logos__link:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; border-radius: 2px; }
.sf-logos__viewport:hover .sf-logos__track, .sf-logos__viewport:focus-within .sf-logos__track, .sf-logos--paused .sf-logos__track { animation-play-state: paused; }
.sf-logos__toggle { position: absolute; right: 8px; bottom: 0; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 999px; background: transparent; color: inherit; cursor: pointer; opacity: 0.55; }
.sf-logos__toggle:hover, .sf-logos__toggle:focus-visible { opacity: 1; }
.sf-logos__toggle:focus-visible { outline: 2px solid currentColor; outline-offset: -4px; }
.sf-logos__icon-play { display: none; }
.sf-logos--paused .sf-logos__icon-play { display: block; }
.sf-logos--paused .sf-logos__icon-pause { display: none; }
.sf-logos__empty { margin: 0 20px; padding: 24px; border: 1px dashed currentColor; border-radius: 8px; text-align: center; opacity: 0.7; }
@keyframes sf-logos-scroll { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
.sf-logos__track { width: auto; animation: none; }
.sf-logos__viewport { -webkit-mask-image: none; mask-image: none; }
.sf-logos__list { flex-wrap: wrap; justify-content: center; row-gap: 24px; min-width: 0; }
.sf-logos__list[aria-hidden="true"] { display: none; }
.sf-logos__toggle { display: none; }
}
{% endstylesheet %}
{% javascript %}
if (!customElements.get('sf-logo-marquee')) {
class SfLogoMarquee extends HTMLElement {
connectedCallback() {
this.userPaused = false;
this.onClick = (event) => {
if (event.target.closest('.sf-logos__toggle')) {
this.userPaused = !this.userPaused;
this.render(this.userPaused);
}
};
this.onSelect = (event) => {
if (this.contains(event.target)) this.render(true);
};
this.onDeselect = (event) => {
if (this.contains(event.target)) this.render(this.userPaused);
};
this.addEventListener('click', this.onClick);
document.addEventListener('shopify:block:select', this.onSelect);
document.addEventListener('shopify:block:deselect', this.onDeselect);
}
disconnectedCallback() {
this.removeEventListener('click', this.onClick);
document.removeEventListener('shopify:block:select', this.onSelect);
document.removeEventListener('shopify:block:deselect', this.onDeselect);
}
render(paused) {
this.classList.toggle('sf-logos--paused', paused);
const toggle = this.querySelector('.sf-logos__toggle');
if (toggle) toggle.setAttribute('aria-pressed', String(paused));
}
}
customElements.define('sf-logo-marquee', SfLogoMarquee);
}
{% endjavascript %}
{% schema %}
{
"name": "SF logo marquee",
"tag": "section",
"class": "sf-logos-section",
"max_blocks": 24,
"settings": [
{ "type": "text", "id": "heading", "label": "Heading", "default": "As featured in" },
{ "type": "range", "id": "logo_height", "label": "Logo height", "min": 20, "max": 80, "step": 2, "unit": "px", "default": 36 },
{ "type": "range", "id": "duration", "label": "Loop duration", "info": "Higher is slower.", "min": 10, "max": 80, "step": 2, "unit": "s", "default": 30 },
{ "type": "header", "content": "Colors" },
{ "type": "color", "id": "text_color", "label": "Text", "default": "#121212" },
{ "type": "color", "id": "background_color", "label": "Background", "default": "#ffffff" },
{ "type": "header", "content": "Spacing" },
{ "type": "range", "id": "padding_top", "label": "Top padding", "min": 0, "max": 100, "step": 4, "unit": "px", "default": 40 },
{ "type": "range", "id": "padding_bottom", "label": "Bottom padding", "min": 0, "max": 100, "step": 4, "unit": "px", "default": 40 }
],
"blocks": [
{
"type": "logo",
"name": "Logo",
"settings": [
{ "type": "image_picker", "id": "logo", "label": "Logo image", "info": "Transparent PNG or SVG works best." },
{ "type": "text", "id": "name", "label": "Brand name", "info": "Used as alt text, and shown as text when no image is set.", "default": "Brand" },
{ "type": "url", "id": "link", "label": "Link" }
]
}
],
"presets": [
{
"name": "SF logo marquee",
"blocks": [
{ "type": "logo", "settings": { "name": "Northvale" } },
{ "type": "logo", "settings": { "name": "Lumen & Co" } },
{ "type": "logo", "settings": { "name": "Atlasworks" } },
{ "type": "logo", "settings": { "name": "Fieldnote" } },
{ "type": "logo", "settings": { "name": "Oakline" } },
{ "type": "logo", "settings": { "name": "Brightside" } }
]
}
]
}
{% endschema %}
- Seamless CSS-only loop — no slider library
- Pause button plus pause on hover and focus
- Static wrapped row for prefers-reduced-motion
- Falls back to a text wordmark when no logo image is set
- Optional link per logo
Add the Logo Marquee to your theme
About two minutes. No app, no monthly fee.
Prefer a walkthrough? See the full installation guide.
- STEP 01
Duplicate your theme
In Shopify admin go to Online Store → Themes. Next to your current theme click ⋯ → Duplicate. Make every change on the copy.
- STEP 02
Create the section file
On the copy, click ⋯ → Edit code. In the sections folder click “Add a new section”, choose Liquid, name it sf-logo-marquee and create it. Delete the starter code, paste ours, then click Save.
- STEP 03
Add it to a page
Click Customize, open the template you want, click “Add section” and choose “SF logo marquee”. Edit the text, blocks and colours in the sidebar, then Save.
- STEP 04
Check it, then publish
Preview on mobile and desktop. When you are happy, publish the duplicate theme.
What you can change in the theme editor
| Setting | Type | Default |
|---|---|---|
| Heading | Text | As featured in |
| Logo height | Slider | 36px |
| Loop durationHigher is slower. | Slider | 30s |
| Text | Colour | #121212 |
| Background | Colour | #ffffff |
| Top padding | Slider | 40px |
| Bottom padding | Slider | 40px |
| Setting | Type | Default |
|---|---|---|
| Logo imageTransparent PNG or SVG works best. | Image | — |
| Brand nameUsed as alt text, and shown as text when no image is set. | Text | Brand |
| Link | Link | — |
This section is one piece of a custom theme.
We design and build complete Shopify themes around your brand.
Common questions
Why is there a pause button?
Moving content that runs longer than five seconds needs a way to pause it under WCAG 2.2.2. The button, hover and keyboard focus all pause the scroll.
What image format should my logos be?
Transparent PNG or SVG uploaded through the image picker. Shopify's CDN serves a resized copy, and the section displays it at the logo height you set.
Will the animation slow my store down?
The scroll is a single CSS transform animation, which browsers run on the compositor, and the logos are lazy-loaded. The only script is a few lines for the pause button.
More free sections
Testimonials Carousel
Free testimonials carousel section for Shopify with star ratings, photos and swipeable cards. No autoplay, keyboard friendly, no slider library.
Trust Badges
Free trust badge section for Shopify: shipping, returns, secure checkout and support icons. Lightweight inline SVG, no JavaScript, no app.
Announcement Marquee
Free scrolling announcement bar for Shopify with multiple messages, links, a pause button and reduced-motion support. Paste the Liquid, no app.
All free Shopify sections
Get a Shopify theme built around your brand
Custom sections, a full theme build, or changes to the theme you already have. Tell us what your store needs and we'll scope it with you.
Not affiliated with or endorsed by Shopify Inc. Shopify is a trademark of Shopify Inc.