Last active
January 8, 2026 16:03
-
-
Save dieseltravis/7a01c2bb80a0758fdfbfa769386360e8 to your computer and use it in GitHub Desktop.
html/css marquee
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>Marquee demo</title> | |
| <style> | |
| html, body { | |
| margin: 0; | |
| padding: 2rem; | |
| background-color: #ddd; | |
| } | |
| .marquee-parent { | |
| width: 50vw; | |
| margin: auto; | |
| padding: 2rem 0; | |
| background-color: #CCF; | |
| display:block; | |
| overflow: hidden; | |
| /* fade at edges */ | |
| -webkit-mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent); | |
| mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent); | |
| } | |
| .marquee { | |
| /* set this to the number of items (sibling-count() not widely supported yet) */ | |
| --item-count: 5; | |
| --duration: calc(3s * var(--item-count)); | |
| /* item width and space between, times count */ | |
| width: calc(240px * var(--item-count)); | |
| /* adjust as needed until entire item isn't visible before disappearing */ | |
| margin-left: -40px; | |
| /* used to pause animation more slowly */ | |
| transform: translateX(0); | |
| transition: 500ms ease-out; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| overflow: hidden; | |
| } | |
| .marquee > .marquee-item { | |
| /* draw an animation path starting at 0, 90 degrees to the right to the end of the element */ | |
| offset: ray(90deg sides at 0); | |
| animation: marquee var(--duration) linear infinite; | |
| /* sibling-index() not widely supported yet, so --item-index is set for each logo */ | |
| /* each item delayed by its index divided by total items times duration */ | |
| animation-delay: calc(-1 * (var(--item-count) - var(--item-index)) * var(--duration) / var(--item-count)); | |
| } | |
| .marquee:hover { | |
| /* transitioned for a less jarring pause */ | |
| transform: translateX(-20px); | |
| } | |
| .marquee:hover > .marquee-item { | |
| animation-play-state: paused; | |
| } | |
| @keyframes marquee { | |
| /* from right to left*/ | |
| from { offset-distance: 100%; } | |
| to { offset-distance: 0%; } | |
| } | |
| /* graceful fallback for when user prefers less motion */ | |
| @media (prefers-reduced-motion: reduce) { | |
| .marquee { | |
| flex-wrap: wrap; | |
| gap: 3.0rem; | |
| } | |
| .marquee:hover { | |
| transform: translateX(0); | |
| } | |
| .marquee .marquee-item { | |
| animation-play-state: paused; | |
| offset: none; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <main> | |
| <div class="marquee-parent"> | |
| <div class="marquee"> | |
| <span class="marquee-item" style="--item-index:1">Item one</span> | |
| <div class="marquee-item" style="--item-index:2"><img src="2" alt="item 2" /></div> | |
| <div class="marquee-item" style="--item-index:3">Item three</div> | |
| <b class="marquee-item" style="--item-index:4">Bold four</b> | |
| <div class="marquee-item" style="--item-index:5">Item five</div> | |
| <!-- be sure to set the css variable --item-count above to the number of items --> | |
| </div> | |
| </div> | |
| </main> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment