NorthJS

Template

Announcement bar section

A dismissible announcement bar with rotating messages, a link and full colour control. Drops into any theme as a section.

Save the Liquid as sections/announcement-bar.liquid, then include the CSS and JavaScript from your theme layout or the section itself. Merchants add one message block per announcement and the bar rotates between them.

Dismissal is stored in sessionStorage, so the bar returns on the next visit rather than disappearing permanently.

Code

Copy a single file, or download all 3 as an archive. Duplicate your theme before pasting into a live store.

  • template.liquidLiquid
    {% comment %}
      Announcement bar — sections/announcement-bar.liquid
    {% endcomment %}
    
    <div
      class="announcement-bar"
      style="--announcement-bg: {{ section.settings.background }}; --announcement-fg: {{ section.settings.text_color }};"
      data-announcement-bar
      data-rotate-ms="{{ section.settings.rotate_seconds | times: 1000 }}"
    >
      <div class="announcement-bar__inner">
        {%- for block in section.blocks -%}
          <p
            class="announcement-bar__message"
            data-announcement-message
            {% unless forloop.first %}hidden{% endunless %}
            {{ block.shopify_attributes }}
          >
            {%- if block.settings.link != blank -%}
              <a class="announcement-bar__link" href="{{ block.settings.link }}">
                {{ block.settings.message | escape }}
              </a>
            {%- else -%}
              {{ block.settings.message | escape }}
            {%- endif -%}
          </p>
        {%- endfor -%}
      </div>
    
      {%- if section.settings.dismissible -%}
        <button
          class="announcement-bar__close"
          type="button"
          data-announcement-close
          aria-label="Dismiss announcement"
        >
          &times;
        </button>
      {%- endif -%}
    </div>
    
    {% schema %}
    {
      "name": "Announcement bar",
      "settings": [
        { "type": "color", "id": "background", "label": "Background", "default": "#111111" },
        { "type": "color", "id": "text_color", "label": "Text", "default": "#ffffff" },
        {
          "type": "range",
          "id": "rotate_seconds",
          "label": "Rotate every",
          "min": 3,
          "max": 15,
          "step": 1,
          "unit": "s",
          "default": 6
        },
        { "type": "checkbox", "id": "dismissible", "label": "Allow dismissing", "default": true }
      ],
      "blocks": [
        {
          "type": "message",
          "name": "Message",
          "limit": 5,
          "settings": [
            { "type": "text", "id": "message", "label": "Message", "default": "Free shipping over $75" },
            { "type": "url", "id": "link", "label": "Link" }
          ]
        }
      ],
      "presets": [
        { "name": "Announcement bar", "blocks": [{ "type": "message" }] }
      ]
    }
    {% endschema %}

  • template.cssCSS
    .announcement-bar {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 0.75rem;
      min-height: 2.5rem;
      padding: 0.5rem 2.5rem;
      background: var(--announcement-bg, #111);
      color: var(--announcement-fg, #fff);
      text-align: center;
      font-size: 0.875rem;
    }
    
    .announcement-bar[hidden] {
      display: none;
    }
    
    .announcement-bar__message {
      margin: 0;
    }
    
    .announcement-bar__link {
      color: inherit;
      text-decoration: underline;
      text-underline-offset: 0.2em;
    }
    
    .announcement-bar__close {
      position: absolute;
      inset-inline-end: 0.5rem;
      padding: 0.25rem 0.5rem;
      border: 0;
      background: none;
      color: inherit;
      font-size: 1.25rem;
      line-height: 1;
      cursor: pointer;
    }
    
    .announcement-bar__close:focus-visible {
      outline: 2px solid currentColor;
      outline-offset: 2px;
    }

  • template.jsJavaScript
    (() => {
      const STORAGE_KEY = 'announcement-bar-dismissed';
    
      function init() {
        const bar = document.querySelector('[data-announcement-bar]');
        if (!bar) return;
    
        if (sessionStorage.getItem(STORAGE_KEY) === 'true') {
          bar.hidden = true;
          return;
        }
    
        bar.querySelector('[data-announcement-close]')?.addEventListener('click', () => {
          bar.hidden = true;
          sessionStorage.setItem(STORAGE_KEY, 'true');
        });
    
        const messages = Array.from(bar.querySelectorAll('[data-announcement-message]'));
        const interval = Number(bar.dataset.rotateMs || 0);
        if (messages.length < 2 || !interval) return;
        if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    
        let index = 0;
        setInterval(() => {
          messages[index].hidden = true;
          index = (index + 1) % messages.length;
          messages[index].hidden = false;
        }, interval);
      }
    
      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init, { once: true });
      } else {
        init();
      }
    
      document.addEventListener('shopify:section:load', init);
    })();