Free Announcement Marquee Section for ShopifyNo app. Copy, paste, done.
- Online Store 2.0
- No app
- Theme Check: 0 errors
- MIT license
The Stackframes announcement marquee is a free Shopify section that scrolls several short messages across a slim bar, such as free shipping, returns or new arrivals. Each message can link somewhere. The loop is pure CSS and pauses on hover, keyboard focus or a pause button. Shoppers who prefer reduced motion see a static row instead.
Live preview with sample content. Once installed, fonts follow your theme and colours are editable in the theme editor.
{%- if section.blocks.size > 0 or request.design_mode -%}
<sf-announcement-marquee
class="sf-announce"
style="--sf-announce-bg: {{ section.settings.background_color }}; --sf-announce-text: {{ section.settings.text_color }}; --sf-announce-duration: {{ section.settings.duration }}s; --sf-announce-size: {{ section.settings.font_size }}px; --sf-announce-py: {{ section.settings.padding }}px;"
>
{%- if section.blocks.size > 0 -%}
<div class="sf-announce__viewport">
<div class="sf-announce__track">
{%- for copy in (1..2) -%}
<ul class="sf-announce__list" role="list" {% if copy == 2 %}aria-hidden="true"{% endif %}>
{%- for block in section.blocks -%}
<li class="sf-announce__item" {% if copy == 1 %}{{ block.shopify_attributes }}{% endif %}>
{%- if block.settings.link != blank and copy == 1 -%}
<a class="sf-announce__link" href="{{ block.settings.link }}">{{ block.settings.text | escape }}</a>
{%- elsif block.settings.link != blank -%}
<span class="sf-announce__text sf-announce__text--link">{{ block.settings.text | escape }}</span>
{%- else -%}
<span class="sf-announce__text">{{ block.settings.text | escape }}</span>
{%- endif -%}
{%- unless section.settings.separator == 'none' -%}
<span class="sf-announce__sep" aria-hidden="true">{% if section.settings.separator == 'star' %}✦{% else %}•{% endif %}</span>
{%- endunless -%}
</li>
{%- endfor -%}
</ul>
{%- endfor -%}
</div>
</div>
<button type="button" class="sf-announce__toggle" aria-pressed="false" aria-label="Pause announcements">
<svg class="sf-announce__icon-pause" aria-hidden="true" focusable="false" viewBox="0 0 20 20" width="18" height="18"><path d="M7 4.5v11M13 4.5v11" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<svg class="sf-announce__icon-play" aria-hidden="true" focusable="false" viewBox="0 0 20 20" width="18" height="18"><path d="M7 4.5v11l8.5-5.5z" fill="currentColor"/></svg>
</button>
{%- else -%}
<p class="sf-announce__empty">Add announcement blocks to show your messages.</p>
{%- endif -%}
</sf-announcement-marquee>
{%- endif -%}
{% stylesheet %}
.sf-announce { display: block; position: relative; overflow: hidden; min-height: 44px; background: var(--sf-announce-bg); color: var(--sf-announce-text); font-size: var(--sf-announce-size); }
.sf-announce__viewport { display: flex; align-items: center; min-height: 44px; overflow: hidden; margin-right: 44px; }
.sf-announce__track { display: flex; width: max-content; animation: sf-announce-scroll var(--sf-announce-duration) linear infinite; }
.sf-announce__list { display: flex; flex: none; align-items: center; justify-content: space-around; gap: 32px; min-width: 100vw; margin: 0; padding: var(--sf-announce-py) 16px; list-style: none; }
.sf-announce__item { display: inline-flex; flex: none; align-items: center; gap: 32px; white-space: nowrap; font-weight: 500; }
.sf-announce__link { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.sf-announce__text--link { text-decoration: underline; text-underline-offset: 3px; }
.sf-announce__link:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; border-radius: 2px; }
.sf-announce__sep { opacity: 0.6; }
.sf-announce__viewport:hover .sf-announce__track, .sf-announce__viewport:focus-within .sf-announce__track, .sf-announce--paused .sf-announce__track { animation-play-state: paused; }
.sf-announce__toggle { position: absolute; top: 0; right: 0; bottom: 0; display: grid; place-items: center; width: 44px; padding: 0; border: 0; background: var(--sf-announce-bg); color: inherit; cursor: pointer; opacity: 0.75; }
.sf-announce__toggle:hover, .sf-announce__toggle:focus-visible { opacity: 1; }
.sf-announce__toggle:focus-visible { outline: 2px solid currentColor; outline-offset: -4px; }
.sf-announce__icon-play { display: none; }
.sf-announce--paused .sf-announce__icon-play { display: block; }
.sf-announce--paused .sf-announce__icon-pause { display: none; }
.sf-announce__empty { margin: 0; padding: 12px 16px; text-align: center; opacity: 0.8; }
@keyframes sf-announce-scroll { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
.sf-announce__viewport { margin-right: 0; }
.sf-announce__track { width: auto; animation: none; }
.sf-announce__list { min-width: 0; flex-wrap: wrap; justify-content: center; white-space: normal; }
.sf-announce__list[aria-hidden="true"] { display: none; }
.sf-announce__toggle { display: none; }
}
{% endstylesheet %}
{% javascript %}
if (!customElements.get('sf-announcement-marquee')) {
class SfAnnouncementMarquee extends HTMLElement {
connectedCallback() {
this.userPaused = false;
this.onClick = (event) => {
if (!event.target.closest('.sf-announce__toggle')) return;
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-announce--paused', paused);
const toggle = this.querySelector('.sf-announce__toggle');
if (toggle) toggle.setAttribute('aria-pressed', String(paused));
}
}
customElements.define('sf-announcement-marquee', SfAnnouncementMarquee);
}
{% endjavascript %}
{% schema %}
{
"name": "SF announcement bar",
"tag": "section",
"class": "sf-announce-section",
"max_blocks": 12,
"settings": [
{ "type": "range", "id": "duration", "label": "Loop duration", "info": "Higher is slower.", "min": 10, "max": 80, "step": 2, "unit": "s", "default": 36 },
{ "type": "range", "id": "font_size", "label": "Text size", "min": 12, "max": 20, "step": 1, "unit": "px", "default": 14 },
{
"type": "select",
"id": "separator",
"label": "Separator",
"options": [
{ "value": "dot", "label": "Dot" },
{ "value": "star", "label": "Star" },
{ "value": "none", "label": "None" }
],
"default": "dot"
},
{ "type": "header", "content": "Colors" },
{ "type": "color", "id": "background_color", "label": "Background", "default": "#111827" },
{ "type": "color", "id": "text_color", "label": "Text", "default": "#ffffff" },
{ "type": "range", "id": "padding", "label": "Vertical padding", "min": 4, "max": 24, "step": 2, "unit": "px", "default": 12 }
],
"blocks": [
{
"type": "message",
"name": "Message",
"settings": [
{ "type": "text", "id": "text", "label": "Text", "default": "Free shipping on orders over $50" },
{ "type": "url", "id": "link", "label": "Link" }
]
}
],
"presets": [
{
"name": "SF announcement bar",
"blocks": [
{ "type": "message", "settings": { "text": "Free shipping on orders over $50", "link": "/collections/all" } },
{ "type": "message", "settings": { "text": "30-day hassle-free returns" } },
{ "type": "message", "settings": { "text": "New arrivals every Friday" } }
]
}
]
}
{% endschema %}
- Multiple messages, each with an optional link
- Seamless CSS loop with a pause button
- Static row for prefers-reduced-motion
- Dot, star or no separator
- Pauses while you edit a message in the theme editor
Add the Announcement 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-announcement-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 announcement bar”. 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 |
|---|---|---|
| Loop durationHigher is slower. | Slider | 36s |
| Text size | Slider | 14px |
| Separator | Dropdown | Dot |
| Background | Colour | #111827 |
| Text | Colour | #ffffff |
| Vertical padding | Slider | 12px |
| Setting | Type | Default |
|---|---|---|
| Text | Text | Free shipping on orders over $50 |
| Link | Link | — |
This section is one piece of a custom theme.
We design and build complete Shopify themes around your brand.
Common questions
Can I use this instead of my theme's announcement bar?
Yes. Add it to the header group in the theme editor and hide your theme's own announcement bar so shoppers only see one.
How do I slow the scroll down?
Increase "Loop duration" in the section settings. Higher values scroll more slowly.
Is scrolling text accessible?
Moving content needs a way to stop it, so the bar has a pause button and also pauses on hover and keyboard focus. Shoppers with reduced motion enabled see the messages without movement.
More free sections
Countdown Timer Bar
Free countdown timer bar for Shopify sales that ends at a real date and time you set, then hides or shows a message. Liquid code, no app.
Shipping Progress Bar
Free shipping progress bar for Shopify that shows how much more to spend, updates when the cart changes, and hides for other currencies. No app.
Logo Marquee
Free scrolling logo bar for Shopify — "as seen in" or partner logos. Pure CSS animation, pause button, reduced-motion friendly. Copy, paste, done.
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.