Ir al contenido
Evaluar mi proyecto
Componentes · FootersDisponible

Footer neobrutalista

Bloques de color con borde grueso y sombra dura, enlaces gigantes que se desplazan y una cinta de texto corrido.

Hagamos ruido

Escríbenos

Código completo

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

footer-neobrutal.tsx72 líneas
Descargar
"use client";

import type { CSSProperties } from "react";

/** Footer neobrutalista: bloques de color con borde grueso y sombra dura, enlaces gigantes y una cinta con texto corrido. React + TypeScript, sin dependencias. */
export type FooterNeobrutalProps = {
  brand?: string;
  cta?: string;
  links?: { label: string; href?: string; color?: string }[];
  legal?: string;
  className?: string;
  style?: CSSProperties;
};

const CSS = `
.gcfnb-root { box-sizing: border-box; container-type: inline-size; width: 100%; padding: clamp(16px, 4cqi, 44px); background: #ffe14d; color: #111; font: 800 16px/1.3 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
.gcfnb-root *, .gcfnb-root *::before, .gcfnb-root *::after { box-sizing: border-box; }
.gcfnb-root :focus-visible { outline: 4px solid #2f5bff; outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .gcfnb-root *, .gcfnb-root *::before, .gcfnb-root *::after { animation: none !important; transition-duration: .01ms !important; } }
.gcfnb-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 18px; }
.gcfnb-box { padding: 22px; border: 4px solid #111; background: #fff; box-shadow: 8px 8px 0 #111; }
.gcfnb-brand { margin: 0 0 10px; font: 900 clamp(34px, 6cqi, 72px)/.9 ui-sans-serif, system-ui, sans-serif; letter-spacing: -.05em; text-transform: uppercase; }
.gcfnb-cta { display: inline-flex; align-items: center; min-height: 50px; padding: 0 22px; border: 4px solid #111; background: #ff90e8; color: #111; font-weight: 900; text-transform: uppercase; text-decoration: none; box-shadow: 5px 5px 0 #111; transition: transform .1s, box-shadow .1s; }
.gcfnb-cta:hover { transform: translate(2px, 2px); box-shadow: 3px 3px 0 #111; }
.gcfnb-cta:active { transform: translate(5px, 5px); box-shadow: 0 0 0 #111; }
.gcfnb-links { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.gcfnb-links a { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; border: 4px solid #111; background: var(--c, #fff); color: #111; font: 900 22px/1 ui-sans-serif, system-ui, sans-serif; text-transform: uppercase; text-decoration: none; transition: transform .1s; }
.gcfnb-links a:hover { transform: translateX(8px); }
.gcfnb-tape { grid-column: 1 / -1; display: flex; overflow: hidden; padding: 0; background: #111; color: #ffe14d; }
.gcfnb-run { display: flex; flex-shrink: 0; gap: 32px; padding: 12px 16px; white-space: nowrap; text-transform: uppercase; letter-spacing: .06em; animation: gcfnb-run 16s linear infinite; }
.gcfnb-legal { margin: 18px 0 0; font-size: 14px; }
@container (max-width: 640px) { .gcfnb-grid { grid-template-columns: 1fr; } }
@keyframes gcfnb-run { to { transform: translateX(-100%); } }`;

const DEFAULT_LINKS = [{ label: "Proyectos", color: "#7cf5c3" }, { label: "Servicios", color: "#8bc8ff" }, { label: "Contacto", color: "#ff9a8a" }];

export function FooterNeobrutal({ brand = "Hagamos ruido", cta = "Escríbenos", links = DEFAULT_LINKS, legal = "© 2026 Hagamos ruido. Todos los derechos reservados, casi todos.", className = "", style }: FooterNeobrutalProps) {
  const phrase = "Sin letra pequeña ✺ Sin sorpresas ✺ Sin relleno ✺ ";
  return (
    <footer className={`gcfnb-root ${className}`} style={style}>
      <style>{CSS}</style>
      <div className="gcfnb-grid">
        <div className="gcfnb-box">
          <p className="gcfnb-brand">{brand}</p>
          <a className="gcfnb-cta" href="#" onClick={(event) => event.preventDefault()}>
            {cta}
          </a>
        </div>
        <nav className="gcfnb-box" aria-label="Pie de página">
          <ul className="gcfnb-links">
            {links.map((link) => (
              <li key={link.label}>
                <a href={link.href ?? "#"} style={{ "--c": link.color } as CSSProperties} onClick={(event) => !link.href && event.preventDefault()}>
                  {link.label} <span aria-hidden="true">→</span>
                </a>
              </li>
            ))}
          </ul>
        </nav>
        <div className="gcfnb-box gcfnb-tape" aria-hidden="true">
          {[0, 1].map((n) => (
            <span key={n} className="gcfnb-run">
              {phrase.repeat(3)}
            </span>
          ))}
        </div>
      </div>
      <p className="gcfnb-legal">{legal}</p>
    </footer>
  );
}

Úsalo en tu proyecto

Instálalo con la CLI de shadcn.

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

Ejemplo de uso de Footer neobrutalista

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

ejemplo.tsx5 líneas
import { FooterNeobrutal } from "./footer-neobrutal";

export default function Ejemplo() {
  return <FooterNeobrutal brand="Ejemplo" />;
}

Propiedades de FooterNeobrutal

FooterNeobrutal acepta 6 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.

PropiedadTipoDescripción
brand?stringOpcional.
cta?stringOpcional.
links?{ label: string; href?: string; color?: string }[]Opcional.
legal?stringOpcional.
className?stringOpcional.
style?CSSPropertiesOpcional.

Personaliza Footer neobrutalista 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
--c#fff

Accesibilidad y rendimiento

El archivo tiene 72 líneas (4 KB) y define 1 animación con @keyframes. Esto es lo que hace Footer neobrutalista 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".
Licencia
MIT
Dependencias
React >=18
Compatibilidad
React 18 y 19 · Next.js (componente de cliente)