Ir al contenido
Evaluar mi proyecto
Componentes · Texto y animacionesDisponible

Marquesina infinita

Contenido que se desplaza sin fin, con bordes que se desvanecen.

EstrategiaDiseñoCódigoDatosProducto
ReactNext.jsTypeScriptPostgreSQLSupabaseTailwindNode.jsDocker

Código completo

Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.

marquee.tsx51 líneas
Descargar
/**
 * Marquesina infinita solo con CSS: el contenido se duplica y se desplaza sin saltos, con bordes que se desvanecen.
 * Se pausa al pasar el puntero o enfocar dentro, y se detiene con movimiento reducido.
 *
 *   <Marquee duration={30}>
 *     <span>React</span><span>Next.js</span><span>TypeScript</span>
 *   </Marquee>
 *   <Marquee reverse duration={40}>…</Marquee>
 *
 * El contenido se hereda en dos copias; la segunda se oculta a lectores de pantalla.
 */

import type { CSSProperties, ReactNode } from "react";

export type MarqueeProps = {
  children: ReactNode;
  /** Segundos que tarda una vuelta completa. */
  duration?: number;
  /** Espacio entre elementos. */
  gap?: number | string;
  reverse?: boolean;
  pauseOnHover?: boolean;
  /** Desvanece los bordes. */
  fade?: boolean;
  className?: string;
  style?: CSSProperties;
};

const CSS = `
.gcmq-root { display: flex; overflow: hidden; width: 100%; }
.gcmq-root[data-fade="true"] { -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); }
.gcmq-track { display: flex; flex: none; min-width: 100%; align-items: center; justify-content: space-around; gap: var(--gcmq-gap, 32px); padding-right: var(--gcmq-gap, 32px); animation: gcmq-run var(--gcmq-duration, 30s) linear infinite; animation-direction: var(--gcmq-direction, normal); }
.gcmq-root[data-pause="true"]:hover .gcmq-track, .gcmq-root[data-pause="true"]:focus-within .gcmq-track { animation-play-state: paused; }
@keyframes gcmq-run { to { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) { .gcmq-track { animation: none; } .gcmq-track[aria-hidden="true"] { display: none; } .gcmq-root { overflow-x: auto; } }
`;

export function Marquee({ children, duration = 30, gap = 32, reverse = false, pauseOnHover = true, fade = true, className, style }: MarqueeProps) {
  const vars = { ["--gcmq-duration" as string]: `${duration}s`, ["--gcmq-gap" as string]: typeof gap === "number" ? `${gap}px` : gap, ["--gcmq-direction" as string]: reverse ? "reverse" : "normal", ...style } as CSSProperties;

  return (
    <>
      <style>{CSS}</style>
      <div className={["gcmq-root", className].filter(Boolean).join(" ")} style={vars} data-fade={fade} data-pause={pauseOnHover}>
        <div className="gcmq-track">{children}</div>
        <div className="gcmq-track" aria-hidden="true">{children}</div>
      </div>
    </>
  );
}

Úsalo en tu proyecto

Instálalo con la CLI de shadcn.

terminal.sh1 líneas
npx shadcn@latest add https://www.gassierconsulting.com/r/marquee-infinito

Ejemplo de uso de Marquesina infinita

Después de copiar marquee.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.

ejemplo.tsx5 líneas
import { Marquee } from "./marquee";

export default function Ejemplo() {
  return <Marquee reverse>Contenido</Marquee>;
}

Propiedades de Marquee

Marquee acepta 8 propiedades; 1 es obligatoria.

PropiedadTipoDescripción
childrenReactNodeObligatoria.
duration?numberSegundos que tarda una vuelta completa.
gap?number | stringEspacio entre elementos.
reverse?booleanOpcional.
pauseOnHover?booleanOpcional.
fade?booleanDesvanece los bordes.
className?stringOpcional.
style?CSSPropertiesOpcional.

Personaliza Marquesina infinita con variables CSS

Define estas variables en el contenedor o en tu hoja de estilos para cambiar los colores sin tocar el componente. Si no las defines, se usa el valor por defecto.

VariableValor por defecto
--gcmq-gap32px
--gcmq-duration30s
--gcmq-directionnormal

Accesibilidad y rendimiento

El archivo tiene 51 líneas (2 KB) y define 1 animación con @keyframes. Esto es lo que hace Marquesina infinita por quien lo usa:

  • Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
  • Expone su estado a tecnologías de apoyo con atributos aria-*.
Licencia
MIT
Dependencias
React >=18
Compatibilidad
React · Next.js · Sin Tailwind

Acerca del producto

Una marquesina que desplaza cualquier contenido sin saltos solo con CSS: duplica el contenido y mueve la pista de cero a menos cien por ciento. Se pausa al pasar el puntero o enfocar, se puede invertir y detiene al reducir el movimiento.

Incluye

Un solo archivo React + TypeScript, con los estilos dentro. No usa Tailwind ni bibliotecas externas.

  • Duración, separación y dirección configurables
  • Bordes que se desvanecen (opcional)
  • Pausa al pasar el puntero o enfocar
  • La copia duplicada se oculta a lectores de pantalla

Cómo usarlo

Pasa tus elementos como hijos. Usa duration más alto para ir más despacio y reverse para invertir el sentido.