Fondo de risografía con grano
Manchas de tinta planas que se mezclan en multiplicación bajo una textura de grano que respira.
Impreso a tres tintas
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 gradiente con grano estilo risografía: manchas de color planas que se deslizan bajo una textura de ruido que respira. Con botón de pausa. React + TypeScript, sin dependencias. */
export type FondoGranoProps = {
children?: ReactNode;
className?: string;
style?: CSSProperties;
};
const GRAIN = "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .9 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>\")";
const CSS = `
.gcfgr-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: #f2e8d5; color: #1d1a16; font: 500 16px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
.gcfgr-root *, .gcfgr-root *::before, .gcfgr-root *::after { box-sizing: border-box; }
.gcfgr-root :focus-visible { outline: 2px solid #1d1a16; outline-offset: 3px; }
.gcfgr-root[data-paused="true"] .gcfgr-s, .gcfgr-root[data-paused="true"] .gcfgr-n { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .gcfgr-s, .gcfgr-n { animation: none !important; } }
.gcfgr-s { position: absolute; z-index: -2; border-radius: 50%; background: var(--c); mix-blend-mode: multiply; will-change: transform; animation: gcfgr-drift var(--t) ease-in-out var(--d) infinite alternate; }
.gcfgr-1 { width: 62%; aspect-ratio: 1; left: -10%; top: -26%; --c: #ff7a59; --t: 15s; --d: 0s; }
.gcfgr-2 { width: 54%; aspect-ratio: 1; right: -12%; top: 6%; --c: #3b6cff; --t: 18s; --d: -5s; }
.gcfgr-3 { width: 46%; aspect-ratio: 1; left: 22%; bottom: -34%; --c: #ffd23f; --t: 21s; --d: -9s; }
.gcfgr-n { position: absolute; inset: -20%; z-index: -1; background-image: ${GRAIN}; opacity: .5; mix-blend-mode: multiply; pointer-events: none; animation: gcfgr-grain 1.2s steps(6) infinite; }
.gcfgr-pause { position: absolute; right: 14px; bottom: 14px; z-index: 3; display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 0 12px; border: 2px solid #1d1a16; border-radius: 4px; background: #f2e8d5; color: #1d1a16; font: 700 12px/1 ui-sans-serif, system-ui, sans-serif; cursor: pointer; }
.gcfgr-pause:hover { background: #fff7e4; }
@keyframes gcfgr-drift { to { transform: translate(18%, 14%) scale(1.15); } }
@keyframes gcfgr-grain { 0% { transform: translate(0, 0); } 20% { transform: translate(-3%, 2%); } 40% { transform: translate(2%, -3%); } 60% { transform: translate(-2%, -2%); } 80% { transform: translate(3%, 3%); } 100% { transform: translate(0, 0); } }`;
export function FondoGrano({ children, className = "", style }: FondoGranoProps) {
const [paused, setPaused] = useState(false);
return (
<section className={`gcfgr-root ${className}`} style={style} data-paused={paused}>
<style>{CSS}</style>
<div className="gcfgr-s gcfgr-1" aria-hidden="true" />
<div className="gcfgr-s gcfgr-2" aria-hidden="true" />
<div className="gcfgr-s gcfgr-3" aria-hidden="true" />
<div className="gcfgr-n" aria-hidden="true" />
{children}
<button className="gcfgr-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-granoEjemplo de uso de Fondo de risografía con grano
Después de copiar fondo-grano.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { FondoGrano } from "./fondo-grano";
export default function Ejemplo() {
return <FondoGrano>Contenido</FondoGrano>;
}Propiedades de FondoGrano
FondoGrano acepta 3 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
children? | ReactNode | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Accesibilidad y rendimiento
El archivo tiene 47 líneas (4 KB) y define 2 animaciones con @keyframes. Esto es lo que hace Fondo de risografía con grano 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".