A good first building block

Scrolling text button

A stable, accessible button with a moving visual label, a pause control and reduced-motion support.

HTMLCSSJavaScriptNo dependencies
Edit in playground

Live preview

Explore the result below

HTML

<main><h1>A little motion, on your terms</h1><button class="scrolling" id="try-button" aria-label="Try this example"><span aria-hidden="true">Try this little example</span></button><p><button id="pause" aria-pressed="false">Pause movement</button></p><p id="button-result" role="status">Choose the moving button to try it.</p></main>
Read the complete HTML document
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>My code example</title>
<style>
:root{font-family:system-ui,sans-serif;color:#18223b}*{box-sizing:border-box}body{margin:0;min-height:100vh;padding:24px;background:#edf1ff;display:grid;place-items:center}main{width:min(100%,480px);background:white;border-radius:20px;padding:24px}h1{font-size:24px;margin:0 0 16px}button,input{font:inherit}button{min-height:44px;border:1px solid #afbddd;border-radius:10px;padding:10px 14px;background:#eff3ff;color:#18223b;cursor:pointer}button:focus-visible,input:focus-visible{outline:3px solid #3658bf;outline-offset:3px}p{line-height:1.65}button:disabled{opacity:.5;cursor:default}.scrolling{width:100%;overflow:hidden;background:#7145b6;color:white}.scrolling span{display:block;animation:move 6s ease-in-out infinite}.scrolling.paused span{animation-play-state:paused}@keyframes move{0%,100%{transform:translateX(-12%)}50%{transform:translateX(12%)}}@media(prefers-reduced-motion:reduce){.scrolling span{animation:none}}
</style>
</head>
<body>
<main><h1>A little motion, on your terms</h1><button class="scrolling" id="try-button" aria-label="Try this example"><span aria-hidden="true">Try this little example</span></button><p><button id="pause" aria-pressed="false">Pause movement</button></p><p id="button-result" role="status">Choose the moving button to try it.</p></main>
<script>
const button=document.querySelector("#try-button"),pause=document.querySelector("#pause"),reduced=matchMedia("(prefers-reduced-motion: reduce)");let count=0,paused=false;
button.addEventListener("click",()=>{count++;document.querySelector("#button-result").textContent="Button activated "+count+" "+(count===1?"time.":"times.");});
function sync(){pause.disabled=reduced.matches;pause.textContent=reduced.matches?"Movement reduced":paused?"Resume movement":"Pause movement";pause.setAttribute("aria-pressed",String(paused||reduced.matches));button.classList.toggle("paused",paused);}
pause.addEventListener("click",()=>{paused=!paused;sync();});reduced.addEventListener("change",sync);sync();
</script>
</body>
</html>

A little guide to making it yours

  1. Copy the code and save it in a file named example.html.
  2. Open the file in your browser to see the complete example.
  3. Change the text and structure in the HTML.
  4. Adjust the colors and spacing in the CSS, or experiment in the playground.

How it works

The accessible name stays constant while the decorative label moves. Motion uses CSS transforms, with a user pause control and a static reduced-motion version. This is newly authored code implementing the historical purpose; the archived preview's jdstiles.com attribution is recorded as provenance, not reassigned to this example.

Historical purpose: 2016 detail and 2017 /view/934.html preview inspected. Historical preview credits jdstiles.com; no source copied and license not established.

Troubleshooting and limits

Pause movement or enable reduced motion for a static label. The accessible button name stays stable while the decorative label moves. Keep the pause button and do not use animation alone to explain an action.

This is newly authored code. It uses system fonts and no external assets.

Keep the ideas going