Docs
Go back
Component by
OV
OblivionGoogle
NETFLIX
Microsoft
Spotify
Google
NETFLIX
Microsoft
Spotify
Google
NETFLIX
Microsoft
Spotify
Google
NETFLIX
Microsoft
Spotify
Vercel
zomato
Uber
stripe
airbnb
Vercel
zomato
Uber
stripe
airbnb
Vercel
zomato
Uber
stripe
airbnb
Vercel
zomato
Uber
stripe
airbnb
TSX
infinite-marquee
"use client"
import React from "react"
export const componentMeta = {
name: "Infinite Marquee",
description: "A seamless infinite scrolling bar with multiple rows, reverse directions, and authentic SVGs.",
props: {}
}
const logosRow1 = [
{ name: "Google", className: "font-sans font-medium tracking-tighter text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" /></svg> },
{ name: "NETFLIX", className: "font-black tracking-widest text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="m5.398 0 8.348 23.602c2.346.059 4.856.398 4.856.398L10.113 0H5.398zm8.489 0v9.172l4.715 13.33V0h-4.715zM5.398 1.5V24c1.873-.225 2.81-.312 4.715-.398V14.83L5.398 1.5z" /></svg> },
{ name: "Microsoft", className: "font-semibold tracking-tight text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M2 2h9v9H2zm11 0h9v9h-9zM2 13h9v9H2zm11 0h9v9h-9z" /></svg> },
{ name: "Spotify", className: "font-bold tracking-tight text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z" /></svg> }
]
const logosRow2 = [
{ name: "Vercel", className: "font-bold tracking-tight text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="m12 1.608 12 20.784H0Z" /></svg> },
{ name: "zomato", className: "font-black italic tracking-tighter text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M19.615 9.45l-1.258.473-.167.71-.446.021-.115.978h.408l-.211 1.51c-.131.939.036 1.381.865 1.381.488 0 .91-.175 1.135-.297l.145-.9c-.167.083-.436.19-.618.19-.247 0-.276-.13-.225-.488l.189-1.396h.843c.03-.206.131-.877.16-1h-.865zm-3.779 1.002c-.115.002-.236.01-.361.026a3.592 3.592 0 0 0-1.347.432l.26.789c.269-.15.615-.28.978-.326.538-.066.757.1.79.375.014.109.004.199-.005.289l-.014.056a3.46 3.46 0 0 0-1.097-.036c-.518.063-.943.273-1.204.6a1.324 1.324 0 0 0-.225 1.034c.127.583.553.84 1.199.76.45-.055.812-.27 1.076-.63a2.665 2.665 0 0 1-.03.304 1.74 1.74 0 0 1-.072.29l1.244.001a3.657 3.657 0 0 1-.001-.365c.036-.459.118-1.143.247-2.051a2.397 2.397 0 0 0-.002-.59c-.08-.644-.628-.969-1.436-.958zm6.536.063c-1.194 0-2.107 1.067-2.107 2.342 0 .959.552 1.693 1.628 1.693 1.2 0 2.107-1.067 2.107-2.35 0-.95-.538-1.685-1.628-1.685zm-11.777.041c-.538 0-1.12.465-1.52 1.236.102-.504.08-1.076.051-1.198a8.964 8.964 0 0 1-1.287.122 6.9 6.9 0 0 1-.073 1.243l-.167 1.145c-.066.45-.138.969-.211 1.297h1.353c.007-.199.058-.511.094-.786l.116-.786c.095-.511.502-1.114.815-1.114.182 0 .175.176.124.504l-.131.885c-.066.45-.138.969-.211 1.297h1.367c.008-.199.051-.512.088-.786l.116-.786c.094-.512.502-1.114.814-1.114.182 0 .175.168.146.396l-.327 2.29H13l.438-2.609c.095-.649.044-1.236-.676-1.236-.523 0-1.09.443-1.49 1.182.087-.61.036-1.182-.677-1.182zm-4.88.008c-1.177 0-2.08 1.053-2.08 2.312 0 .946.546 1.67 1.608 1.67 1.185 0 2.08-1.052 2.08-2.319 0-.938-.531-1.663-1.607-1.663zm-5.126.091c-.05.39-.102.778-.175 1.13.328-.008.619-.016 1.411-.016l-1.81 1.96-.015.703c.444-.03.997-.039 1.63-.039.566 0 1.134.008 1.497.039.065-.458.13-.763.21-1.137-.275.015-.755.023-1.512.023l1.81-1.969.023-.694c-.437.023-.83.03-1.52.03-.749 0-.975-.007-1.549-.03zm4.988.927c.255 0 .408.228.408.701 0 .687-.276 1.251-.626 1.251-.261 0-.414-.236-.414-.702 0-.694.283-1.25.632-1.25zm16.629 0c.254 0 .407.228.407.701 0 .687-.276 1.251-.625 1.251-.262 0-.415-.236-.415-.702 0-.694.284-1.25.633-1.25zM15.51 12.64c.206-.003.403.024.55.058l-.013.118c-.075.44-.39.881-.848.938-.31.037-.578-.148-.608-.39a.538.538 0 0 1 .114-.41c.117-.159.336-.268.599-.3.069-.009.138-.013.206-.014Z" /></svg> },
{ name: "Uber", className: "font-normal tracking-wide text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M0 7.97v4.958c0 1.867 1.302 3.101 3 3.101.826 0 1.562-.316 2.094-.87v.736H6.27V7.97H5.082v4.888c0 1.257-.85 2.106-1.947 2.106-1.11 0-1.946-.827-1.946-2.106V7.971H0zm7.44 0v7.925h1.13v-.725c.521.532 1.257.86 2.06.86a3.006 3.006 0 0 0 3.034-3.01 3.01 3.01 0 0 0-3.033-3.024 2.86 2.86 0 0 0-2.049.861V7.971H7.439zm9.869 2.038c-1.687 0-2.965 1.37-2.965 3 0 1.72 1.334 3.01 3.066 3.01 1.053 0 1.913-.463 2.49-1.233l-.826-.611c-.43.577-.996.847-1.664.847-.973 0-1.753-.7-1.912-1.64h4.697v-.373c0-1.72-1.222-3-2.886-3zm6.295.068c-.634 0-1.098.294-1.381.758v-.713h-1.131v5.774h1.142V12.61c0-.894.544-1.47 1.291-1.47H24v-1.065h-.396zm-6.319.928c.85 0 1.564.588 1.756 1.47H15.52c.203-.882.916-1.47 1.765-1.47zm-6.732.012c1.086 0 1.98.883 1.98 2.004a1.993 1.993 0 0 1-1.98 2.001A1.989 1.989 0 0 1 8.56 13.02a1.99 1.99 0 0 1 1.992-2.004z" /></svg> },
{ name: "stripe", className: "font-bold tracking-tighter text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M13.976 9.15c-2.172-.806-3.356-1.426-3.356-2.409 0-.831.683-1.305 1.901-1.305 2.227 0 4.515.858 6.09 1.631l.89-5.494C18.252.975 15.697 0 12.165 0 9.667 0 7.589.654 6.104 1.872 4.56 3.147 3.757 4.992 3.757 7.218c0 4.039 2.467 5.76 6.476 7.219 2.585.92 3.445 1.574 3.445 2.583 0 .98-.84 1.545-2.354 1.545-1.875 0-4.965-.921-6.99-2.109l-.9 5.555C5.175 22.99 8.385 24 11.714 24c2.641 0 4.843-.624 6.328-1.813 1.664-1.305 2.525-3.236 2.525-5.732 0-4.128-2.524-5.851-6.594-7.305h.003z" /></svg> },
{ name: "airbnb", className: "font-bold tracking-tighter text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M12.001 18.275c-1.353-1.697-2.148-3.184-2.413-4.457-.263-1.027-.16-1.848.291-2.465.477-.71 1.188-1.056 2.121-1.056s1.643.345 2.12 1.063c.446.61.558 1.432.286 2.465-.291 1.298-1.085 2.785-2.412 4.458zm9.601 1.14c-.185 1.246-1.034 2.28-2.2 2.783-2.253.98-4.483-.583-6.392-2.704 3.157-3.951 3.74-7.028 2.385-9.018-.795-1.14-1.933-1.695-3.394-1.695-2.944 0-4.563 2.49-3.927 5.382.37 1.565 1.352 3.343 2.917 5.332-.98 1.085-1.91 1.856-2.732 2.333-.636.344-1.245.558-1.828.609-2.679.399-4.778-2.2-3.825-4.88.132-.345.395-.98.845-1.961l.025-.053c1.464-3.178 3.242-6.79 5.285-10.795l.053-.132.58-1.116c.45-.822.635-1.19 1.351-1.643.346-.21.77-.315 1.246-.315.954 0 1.698.558 2.016 1.007.158.239.345.557.582.953l.558 1.089.08.159c2.041 4.004 3.821 7.608 5.279 10.794l.026.025.533 1.22.318.764c.243.613.294 1.222.213 1.858zm1.22-2.39c-.186-.583-.505-1.271-.9-2.094v-.03c-1.889-4.006-3.642-7.608-5.307-10.844l-.111-.163C15.317 1.461 14.468 0 12.001 0c-2.44 0-3.476 1.695-4.535 3.898l-.081.16c-1.669 3.236-3.421 6.843-5.303 10.847v.053l-.559 1.22c-.21.504-.317.768-.345.847C-.172 20.74 2.611 24 5.98 24c.027 0 .132 0 .265-.027h.372c1.75-.213 3.554-1.325 5.384-3.317 1.829 1.989 3.635 3.104 5.382 3.317h.372c.133.027.239.027.265.027 3.37.003 6.152-3.261 4.802-6.975z" /></svg> }
]
export default function InfiniteMarquee() {
return (
<div className="flex flex-col items-center justify-center w-full relative py-12 overflow-hidden">
{/* Keyframes: ob-marquee-fwd / ob-marquee-rev — defined in globals.css */}
<style dangerouslySetInnerHTML={{ __html: `
@keyframes ob-marquee-fwd {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
@keyframes ob-marquee-rev {
from { transform: translateX(-50%); }
to { transform: translateX(0); }
}
.ob-marquee-fwd {
animation: ob-marquee-fwd 45s linear infinite;
}
.ob-marquee-rev {
animation: ob-marquee-rev 50s linear infinite;
}
`}} />
{/* Fade Masks — uses --ob-surface-0 token, not hardcoded hex */}
<div className="pointer-events-none absolute inset-y-0 left-0 w-1/4 z-10"
style={{ background: 'linear-gradient(to right, var(--ob-surface-0), transparent)' }} />
<div className="pointer-events-none absolute inset-y-0 right-0 w-1/4 z-10"
style={{ background: 'linear-gradient(to left, var(--ob-surface-0), transparent)' }} />
{/* Row 1 - Moving Left */}
<div className="flex w-full overflow-hidden mb-12 opacity-80 mix-blend-multiply dark:mix-blend-screen">
<div className="flex w-max ob-marquee-fwd items-center text-neutral-400 dark:text-neutral-500">
{[...logosRow1, ...logosRow1, ...logosRow1, ...logosRow1].map((logo, i) => (
<div
key={i}
className="mx-12 md:mx-20 flex items-center justify-center whitespace-nowrap grayscale hover:grayscale-0 transition-all duration-300 cursor-default"
>
{logo.icon}
<span className={logo.className}>
{logo.name}
</span>
</div>
))}
</div>
</div>
{/* Row 2 - Moving Right (Reverse) */}
<div className="flex w-full overflow-hidden opacity-80 mix-blend-multiply dark:mix-blend-screen hidden md:flex">
<div className="flex w-max ob-marquee-rev items-center text-neutral-400 dark:text-neutral-500">
{[...logosRow2, ...logosRow2, ...logosRow2, ...logosRow2].map((logo, i) => (
<div
key={i}
className="mx-12 md:mx-20 flex items-center justify-center whitespace-nowrap grayscale hover:grayscale-0 transition-all duration-300 cursor-default"
>
{logo.icon}
<span className={logo.className}>
{logo.name}
</span>
</div>
))}
</div>
</div>
</div>
)
}"use client"
import React from "react"
export const componentMeta = {
name: "Infinite Marquee",
description: "A seamless infinite scrolling bar with multiple rows, reverse directions, and authentic SVGs.",
props: {}
}
const logosRow1 = [
{ name: "Google", className: "font-sans font-medium tracking-tighter text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" /></svg> },
{ name: "NETFLIX", className: "font-black tracking-widest text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="m5.398 0 8.348 23.602c2.346.059 4.856.398 4.856.398L10.113 0H5.398zm8.489 0v9.172l4.715 13.33V0h-4.715zM5.398 1.5V24c1.873-.225 2.81-.312 4.715-.398V14.83L5.398 1.5z" /></svg> },
{ name: "Microsoft", className: "font-semibold tracking-tight text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M2 2h9v9H2zm11 0h9v9h-9zM2 13h9v9H2zm11 0h9v9h-9z" /></svg> },
{ name: "Spotify", className: "font-bold tracking-tight text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.66 0 12 0zm5.521 17.34c-.24.359-.66.48-1.021.24-2.82-1.74-6.36-2.101-10.561-1.141-.418.122-.779-.179-.899-.539-.12-.421.18-.78.54-.9 4.56-1.021 8.52-.6 11.64 1.32.42.18.479.659.301 1.02zm1.44-3.3c-.301.42-.841.6-1.262.3-3.239-1.98-8.159-2.58-11.939-1.38-.479.12-1.02-.12-1.14-.6-.12-.48.12-1.021.6-1.141C9.6 9.9 15 10.561 18.72 12.84c.361.181.54.78.241 1.2zm.12-3.36C15.24 8.4 8.82 8.16 5.16 9.301c-.6.179-1.2-.181-1.38-.721-.18-.601.18-1.2.72-1.381 4.26-1.26 11.28-1.02 15.721 1.621.539.3.719 1.02.419 1.56-.299.421-1.02.599-1.559.3z" /></svg> }
]
const logosRow2 = [
{ name: "Vercel", className: "font-bold tracking-tight text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="m12 1.608 12 20.784H0Z" /></svg> },
{ name: "zomato", className: "font-black italic tracking-tighter text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M19.615 9.45l-1.258.473-.167.71-.446.021-.115.978h.408l-.211 1.51c-.131.939.036 1.381.865 1.381.488 0 .91-.175 1.135-.297l.145-.9c-.167.083-.436.19-.618.19-.247 0-.276-.13-.225-.488l.189-1.396h.843c.03-.206.131-.877.16-1h-.865zm-3.779 1.002c-.115.002-.236.01-.361.026a3.592 3.592 0 0 0-1.347.432l.26.789c.269-.15.615-.28.978-.326.538-.066.757.1.79.375.014.109.004.199-.005.289l-.014.056a3.46 3.46 0 0 0-1.097-.036c-.518.063-.943.273-1.204.6a1.324 1.324 0 0 0-.225 1.034c.127.583.553.84 1.199.76.45-.055.812-.27 1.076-.63a2.665 2.665 0 0 1-.03.304 1.74 1.74 0 0 1-.072.29l1.244.001a3.657 3.657 0 0 1-.001-.365c.036-.459.118-1.143.247-2.051a2.397 2.397 0 0 0-.002-.59c-.08-.644-.628-.969-1.436-.958zm6.536.063c-1.194 0-2.107 1.067-2.107 2.342 0 .959.552 1.693 1.628 1.693 1.2 0 2.107-1.067 2.107-2.35 0-.95-.538-1.685-1.628-1.685zm-11.777.041c-.538 0-1.12.465-1.52 1.236.102-.504.08-1.076.051-1.198a8.964 8.964 0 0 1-1.287.122 6.9 6.9 0 0 1-.073 1.243l-.167 1.145c-.066.45-.138.969-.211 1.297h1.353c.007-.199.058-.511.094-.786l.116-.786c.095-.511.502-1.114.815-1.114.182 0 .175.176.124.504l-.131.885c-.066.45-.138.969-.211 1.297h1.367c.008-.199.051-.512.088-.786l.116-.786c.094-.512.502-1.114.814-1.114.182 0 .175.168.146.396l-.327 2.29H13l.438-2.609c.095-.649.044-1.236-.676-1.236-.523 0-1.09.443-1.49 1.182.087-.61.036-1.182-.677-1.182zm-4.88.008c-1.177 0-2.08 1.053-2.08 2.312 0 .946.546 1.67 1.608 1.67 1.185 0 2.08-1.052 2.08-2.319 0-.938-.531-1.663-1.607-1.663zm-5.126.091c-.05.39-.102.778-.175 1.13.328-.008.619-.016 1.411-.016l-1.81 1.96-.015.703c.444-.03.997-.039 1.63-.039.566 0 1.134.008 1.497.039.065-.458.13-.763.21-1.137-.275.015-.755.023-1.512.023l1.81-1.969.023-.694c-.437.023-.83.03-1.52.03-.749 0-.975-.007-1.549-.03zm4.988.927c.255 0 .408.228.408.701 0 .687-.276 1.251-.626 1.251-.261 0-.414-.236-.414-.702 0-.694.283-1.25.632-1.25zm16.629 0c.254 0 .407.228.407.701 0 .687-.276 1.251-.625 1.251-.262 0-.415-.236-.415-.702 0-.694.284-1.25.633-1.25zM15.51 12.64c.206-.003.403.024.55.058l-.013.118c-.075.44-.39.881-.848.938-.31.037-.578-.148-.608-.39a.538.538 0 0 1 .114-.41c.117-.159.336-.268.599-.3.069-.009.138-.013.206-.014Z" /></svg> },
{ name: "Uber", className: "font-normal tracking-wide text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M0 7.97v4.958c0 1.867 1.302 3.101 3 3.101.826 0 1.562-.316 2.094-.87v.736H6.27V7.97H5.082v4.888c0 1.257-.85 2.106-1.947 2.106-1.11 0-1.946-.827-1.946-2.106V7.971H0zm7.44 0v7.925h1.13v-.725c.521.532 1.257.86 2.06.86a3.006 3.006 0 0 0 3.034-3.01 3.01 3.01 0 0 0-3.033-3.024 2.86 2.86 0 0 0-2.049.861V7.971H7.439zm9.869 2.038c-1.687 0-2.965 1.37-2.965 3 0 1.72 1.334 3.01 3.066 3.01 1.053 0 1.913-.463 2.49-1.233l-.826-.611c-.43.577-.996.847-1.664.847-.973 0-1.753-.7-1.912-1.64h4.697v-.373c0-1.72-1.222-3-2.886-3zm6.295.068c-.634 0-1.098.294-1.381.758v-.713h-1.131v5.774h1.142V12.61c0-.894.544-1.47 1.291-1.47H24v-1.065h-.396zm-6.319.928c.85 0 1.564.588 1.756 1.47H15.52c.203-.882.916-1.47 1.765-1.47zm-6.732.012c1.086 0 1.98.883 1.98 2.004a1.993 1.993 0 0 1-1.98 2.001A1.989 1.989 0 0 1 8.56 13.02a1.99 1.99 0 0 1 1.992-2.004z" /></svg> },
{ name: "stripe", className: "font-bold tracking-tighter text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M13.976 9.15c-2.172-.806-3.356-1.426-3.356-2.409 0-.831.683-1.305 1.901-1.305 2.227 0 4.515.858 6.09 1.631l.89-5.494C18.252.975 15.697 0 12.165 0 9.667 0 7.589.654 6.104 1.872 4.56 3.147 3.757 4.992 3.757 7.218c0 4.039 2.467 5.76 6.476 7.219 2.585.92 3.445 1.574 3.445 2.583 0 .98-.84 1.545-2.354 1.545-1.875 0-4.965-.921-6.99-2.109l-.9 5.555C5.175 22.99 8.385 24 11.714 24c2.641 0 4.843-.624 6.328-1.813 1.664-1.305 2.525-3.236 2.525-5.732 0-4.128-2.524-5.851-6.594-7.305h.003z" /></svg> },
{ name: "airbnb", className: "font-bold tracking-tighter text-3xl md:text-4xl", icon: <svg viewBox="0 0 24 24" className="w-8 h-8 mr-3 fill-current"><path d="M12.001 18.275c-1.353-1.697-2.148-3.184-2.413-4.457-.263-1.027-.16-1.848.291-2.465.477-.71 1.188-1.056 2.121-1.056s1.643.345 2.12 1.063c.446.61.558 1.432.286 2.465-.291 1.298-1.085 2.785-2.412 4.458zm9.601 1.14c-.185 1.246-1.034 2.28-2.2 2.783-2.253.98-4.483-.583-6.392-2.704 3.157-3.951 3.74-7.028 2.385-9.018-.795-1.14-1.933-1.695-3.394-1.695-2.944 0-4.563 2.49-3.927 5.382.37 1.565 1.352 3.343 2.917 5.332-.98 1.085-1.91 1.856-2.732 2.333-.636.344-1.245.558-1.828.609-2.679.399-4.778-2.2-3.825-4.88.132-.345.395-.98.845-1.961l.025-.053c1.464-3.178 3.242-6.79 5.285-10.795l.053-.132.58-1.116c.45-.822.635-1.19 1.351-1.643.346-.21.77-.315 1.246-.315.954 0 1.698.558 2.016 1.007.158.239.345.557.582.953l.558 1.089.08.159c2.041 4.004 3.821 7.608 5.279 10.794l.026.025.533 1.22.318.764c.243.613.294 1.222.213 1.858zm1.22-2.39c-.186-.583-.505-1.271-.9-2.094v-.03c-1.889-4.006-3.642-7.608-5.307-10.844l-.111-.163C15.317 1.461 14.468 0 12.001 0c-2.44 0-3.476 1.695-4.535 3.898l-.081.16c-1.669 3.236-3.421 6.843-5.303 10.847v.053l-.559 1.22c-.21.504-.317.768-.345.847C-.172 20.74 2.611 24 5.98 24c.027 0 .132 0 .265-.027h.372c1.75-.213 3.554-1.325 5.384-3.317 1.829 1.989 3.635 3.104 5.382 3.317h.372c.133.027.239.027.265.027 3.37.003 6.152-3.261 4.802-6.975z" /></svg> }
]
export default function InfiniteMarquee() {
return (
<div className="flex flex-col items-center justify-center w-full relative py-12 overflow-hidden">
{/* Keyframes: ob-marquee-fwd / ob-marquee-rev — defined in globals.css */}
<style dangerouslySetInnerHTML={{ __html: `
@keyframes ob-marquee-fwd {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
@keyframes ob-marquee-rev {
from { transform: translateX(-50%); }
to { transform: translateX(0); }
}
.ob-marquee-fwd {
animation: ob-marquee-fwd 45s linear infinite;
}
.ob-marquee-rev {
animation: ob-marquee-rev 50s linear infinite;
}
`}} />
{/* Fade Masks — uses --ob-surface-0 token, not hardcoded hex */}
<div className="pointer-events-none absolute inset-y-0 left-0 w-1/4 z-10"
style={{ background: 'linear-gradient(to right, var(--ob-surface-0), transparent)' }} />
<div className="pointer-events-none absolute inset-y-0 right-0 w-1/4 z-10"
style={{ background: 'linear-gradient(to left, var(--ob-surface-0), transparent)' }} />
{/* Row 1 - Moving Left */}
<div className="flex w-full overflow-hidden mb-12 opacity-80 mix-blend-multiply dark:mix-blend-screen">
<div className="flex w-max ob-marquee-fwd items-center text-neutral-400 dark:text-neutral-500">
{[...logosRow1, ...logosRow1, ...logosRow1, ...logosRow1].map((logo, i) => (
<div
key={i}
className="mx-12 md:mx-20 flex items-center justify-center whitespace-nowrap grayscale hover:grayscale-0 transition-all duration-300 cursor-default"
>
{logo.icon}
<span className={logo.className}>
{logo.name}
</span>
</div>
))}
</div>
</div>
{/* Row 2 - Moving Right (Reverse) */}
<div className="flex w-full overflow-hidden opacity-80 mix-blend-multiply dark:mix-blend-screen hidden md:flex">
<div className="flex w-max ob-marquee-rev items-center text-neutral-400 dark:text-neutral-500">
{[...logosRow2, ...logosRow2, ...logosRow2, ...logosRow2].map((logo, i) => (
<div
key={i}
className="mx-12 md:mx-20 flex items-center justify-center whitespace-nowrap grayscale hover:grayscale-0 transition-all duration-300 cursor-default"
>
{logo.icon}
<span className={logo.className}>
{logo.name}
</span>
</div>
))}
</div>
</div>
</div>
)
}Save to favoritesCopy to Figma
React
Infinite Marquee
A seamless infinite scrolling bar with multiple rows, reverse directions, and authentic SVGs.
Installation
$ npx @cosmoo/oblivion add infinite-marqueeDependencies
npm install Usage Example
tsx
import InfiniteMarquee from "@/components/oblivion/infinite-marquee"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<InfiniteMarquee />
</div>
)
}import InfiniteMarquee from "@/components/oblivion/infinite-marquee"
export default function Demo() {
return (
<div className="p-10 flex justify-center">
<InfiniteMarquee />
</div>
)
}