Loading Developer Playground

Loading ...

Skip to main content
ARIA ROLELive Region Roles

marquee

A type of live region where non-essential information changes frequently. Marquee updates are not announced to screen readers by default, making it suitable for decorative or supplementary content.

Implicit aria-live
off
Implicit aria-atomic
false
Required Attributes
None

Overview

The marquee role is for non-essential information that changes frequently. With aria-live="off" by default, these updates are not announced to screen readers.

Use marquee for decorative content like stock tickers, news tickers, or rotating banners where the information is supplementary and users can access it through other means if needed.

Provide Alternatives

Since marquee content isn't announced, always provide an alternative way for screen reader users to access the information (e.g., a static list, details element, or separate page).

Live Demo: Stock Ticker

$150.25
ACME Stock Price

Note: This ticker updates every 2 seconds, but screen readers do NOT announce the changes. Users can view it visually or access a static price list elsewhere.

Code Examples

Basic Marquee

<!-- Basic Marquee (Stock Ticker) -->
<div role="marquee" aria-label="Stock Prices">
  <span>AAPL: $150.25</span>
  <span>GOOGL: $2,800.50</span>
  <span>MSFT: $310.75</span>
</div>

<!-- Implicit aria-live="off" - updates are NOT announced -->
<!-- This is appropriate for non-essential, rapidly changing data -->

Stock Ticker

<!-- Stock Ticker / News Ticker -->
<div id="stock-ticker" 
     role="marquee" 
     aria-label="Live Stock Prices"
     class="ticker">
  <div class="ticker-content">
    <span class="stock">AAPL: <strong id="aapl">$150.25</strong></span>
    <span class="stock">GOOGL: <strong id="googl">$2,800.50</strong></span>
    <span class="stock">MSFT: <strong id="msft">$310.75</strong></span>
  </div>
</div>

<script>
  // Update prices every second
  setInterval(async () => {
    const prices = await fetchStockPrices();
    document.getElementById('aapl').textContent = `$${prices.AAPL}`;
    document.getElementById('googl').textContent = `$${prices.GOOGL}`;
    document.getElementById('msft').textContent = `$${prices.MSFT}`;
    
    // Screen readers do NOT announce these updates
    // (because aria-live="off" by default)
  }, 1000);
</script>

News Ticker

<!-- News Ticker / Scrolling Text -->
<div role="marquee" 
     aria-label="Breaking News Ticker"
     class="news-ticker">
  <div class="ticker-text">
    Breaking: New product launch announced • 
    Weather: Sunny, 75°F • 
    Sports: Team wins championship • 
    Traffic: Highway 101 delays expected
  </div>
</div>

<style>
  .news-ticker {
    overflow: hidden;
    white-space: nowrap;
  }
  
  .ticker-text {
    display: inline-block;
    animation: scroll-left 30s linear infinite;
  }
  
  @keyframes scroll-left {
    from { transform: translateX(100%); }
    to { transform: translateX(-100%); }
  }
</style>

<!-- Note: Provide alternative way to access this information
     since screen readers don't announce it -->

React Component

// React Marquee Component
import { useState, useEffect } from 'react';

function StockTicker({ stocks }) {
  const [prices, setPrices] = useState(stocks);
  
  useEffect(() => {
    // Simulate real-time price updates
    const interval = setInterval(async () => {
      const updated = await fetchLatestPrices();
      setPrices(updated);
    }, 2000);
    
    return () => clearInterval(interval);
  }, []);
  
  return (
    <div
      role="marquee"
      aria-label="Stock Price Ticker"
      className="stock-ticker"
    >
      {prices.map(stock => (
        <div key={stock.symbol} className="stock-item">
          <span className="symbol">{stock.symbol}</span>
          <span className={stock.change >= 0 ? 'positive' : 'negative'}>
            {'$'}{stock.price.toFixed(2)}
          </span>
          <span className="change">
            {stock.change >= 0 ? '▲' : '▼'} 
            {Math.abs(stock.change).toFixed(2)}%
          </span>
        </div>
      ))}
    </div>
  );
}

// News Ticker Example
function NewsTicker({ items }) {
  return (
    <>
      {/* Visual marquee (not announced) */}
      <div
        role="marquee"
        aria-label="Breaking News"
        className="marquee-container"
      >
        <div className="scrolling-text">
          {items.map((item, i) => (
            <span key={i}>{item} • </span>
          ))}
        </div>
      </div>
      
      {/* Alternative: Accessible news list */}
      <details className="sr-only">
        <summary>View all news items</summary>
        <ul>
          {items.map((item, i) => (
            <li key={i}>{item}</li>
          ))}
        </ul>
      </details>
    </>
  );
}

Best Practices

Use for non-essential, rapidly updating content

Provide alternative access to the information

Use for stock tickers, news tickers, live scores

Add aria-label to describe the marquee content

Consider if the information is truly non-essential

×

Don't use for important information users must see

×

Don't use as only way to present critical data

×

Don't forget to provide accessible alternatives

Specifications & Resources