Fondo de olas en capas
Cuatro curvas SVG con paralaje que se desplazan a distinta velocidad bajo un sol de atardecer.
Marea de verano
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
"use client";
import { useState, type CSSProperties, type ReactNode } from "react";
/** Fondo de olas en capas: cuatro curvas SVG con paralaje que se desplazan a distinta velocidad sobre un cielo degradado. Con botón de pausa. React + TypeScript, sin dependencias. */
export type FondoOlasProps = {
colors?: [string, string, string, string];
sky?: string;
children?: ReactNode;
className?: string;
style?: CSSProperties;
};
const CSS = `
.gcfol-root { box-sizing: border-box; position: relative; isolation: isolate; container-type: inline-size; width: 100%; min-height: 480px; overflow: hidden; display: grid; place-items: center; background: var(--gcfol-sky, linear-gradient(180deg, #ffe3c7, #ffb7a0 55%, #ff8fa3)); color: #fff; font: 500 16px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
.gcfol-root *, .gcfol-root *::before, .gcfol-root *::after { box-sizing: border-box; }
.gcfol-root :focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.gcfol-root[data-paused="true"] .gcfol-w { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .gcfol-w { animation: none !important; } }
.gcfol-sun { position: absolute; z-index: -3; left: 50%; bottom: 34%; width: min(36cqi, 260px); aspect-ratio: 1; margin-left: calc(min(36cqi, 260px) / -2); border-radius: 50%; background: radial-gradient(circle, #fff7cf 0 55%, rgba(255, 247, 207, .0) 72%); box-shadow: 0 0 80px 30px rgba(255, 238, 190, .6); }
.gcfol-waves { position: absolute; left: 0; right: 0; bottom: 0; height: 56%; z-index: -1; }
.gcfol-w { position: absolute; left: 0; bottom: 0; width: 200%; height: var(--h); animation: gcfol-slide var(--t) linear infinite var(--dir, normal); }
.gcfol-w svg { display: block; width: 100%; height: 100%; }
.gcfol-pause { position: absolute; right: 14px; top: 14px; z-index: 3; display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 12px; border: 0; border-radius: 999px; background: rgba(40, 20, 60, .45); color: #fff; font: 600 12px/1 ui-sans-serif, system-ui, sans-serif; cursor: pointer; }
.gcfol-pause:hover { background: rgba(40, 20, 60, .6); }
@keyframes gcfol-slide { to { transform: translateX(-50%); } }`;
const PATH = "M0 60 C 120 20 240 100 360 60 S 600 20 720 60 S 960 100 1080 60 S 1320 20 1440 60 S 1680 100 1800 60 S 2040 20 2160 60 S 2400 100 2520 60 S 2760 20 2880 60 V 200 H 0 Z";
export function FondoOlas({ colors = ["#ff7a8a", "#e0568f", "#9b3f9a", "#5a2a7a"], sky, children, className = "", style }: FondoOlasProps) {
const [paused, setPaused] = useState(false);
const layers = [
{ h: "88%", t: "34s", dir: "normal" },
{ h: "70%", t: "26s", dir: "reverse" },
{ h: "52%", t: "19s", dir: "normal" },
{ h: "34%", t: "13s", dir: "reverse" },
];
return (
<section className={`gcfol-root ${className}`} style={{ ...(sky ? ({ "--gcfol-sky": sky } as CSSProperties) : {}), ...style }} data-paused={paused}>
<style>{CSS}</style>
<div className="gcfol-sun" aria-hidden="true" />
<div className="gcfol-waves" aria-hidden="true">
{layers.map((layer, i) => (
<div key={i} className="gcfol-w" style={{ "--h": layer.h, "--t": layer.t, "--dir": layer.dir } as CSSProperties}>
<svg viewBox="0 0 2880 200" preserveAspectRatio="none">
<path d={PATH} fill={colors[i]} transform={`translate(${i * -240} 0)`} />
</svg>
</div>
))}
</div>
{children}
<button className="gcfol-pause" type="button" aria-pressed={paused} onClick={() => setPaused((value) => !value)}>
<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">{paused ? <path d="M7 4v16l13-8z" /> : <path d="M6 4h4v16H6zM14 4h4v16h-4z" />}</svg>
{paused ? "Reanudar" : "Pausar"} fondo
</button>
</section>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/fondo-olasEjemplo de uso de Fondo de olas en capas
Después de copiar fondo-olas.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { FondoOlas } from "./fondo-olas";
export default function Ejemplo() {
return <FondoOlas sky="Ejemplo">Contenido</FondoOlas>;
}Propiedades de FondoOlas
FondoOlas acepta 5 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
colors? | [string, string, string, string] | Opcional. |
sky? | string | Opcional. |
children? | ReactNode | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Personaliza Fondo de olas en capas 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.
| Variable | Valor por defecto |
|---|---|
--dir | normal |
Accesibilidad y rendimiento
El archivo tiene 59 líneas (4 KB) y define 1 animación con @keyframes. Esto es lo que hace Fondo de olas en capas por quien lo usa:
- Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
- Muestra un anillo de foco visible al navegar con teclado (:focus-visible).
- Expone su estado a tecnologías de apoyo con atributos aria-*.
- Es un componente de cliente de Next.js: incluye la directiva "use client".