Cómo crear un footer oscuro y minimalista en React
Un footer oscuro minimalista en React centra el nombre de marca, los enlaces de navegación, los enlaces sociales y el copyright en una única columna vertical mediante flexbox y propiedades CSS personalizadas para el tema. No se necesita ninguna librería externa; los estados hover se gestionan con handlers onMouseEnter/onMouseLeave inline.
- Stack: React (componente cliente), propiedades CSS personalizadas, cero dependencias externas, ~130 líneas.
- Animación: solo CSS, transición de color en los enlaces a 0.15s, sin Framer Motion.
- Layout: una única columna flexbox centrada; cada sección es opcional y solo se renderiza cuando se proporcionan datos.
- Accesible: etiquetas anchor nativas, elemento footer semántico, contraste de texto al 40-50% de blanco sobre fondo oscuro.
- Responsive por defecto; flexWrap en la fila de navegación gestiona los viewports estrechos.
Footer Dark Minimal es un footer React centrado y apilado en columna para sitios con tema oscuro. Renderiza un nombre de marca como enlace en mayúsculas, un tagline opcional, una fila de navegación con salto de línea, una fila de enlaces sociales y una línea de copyright, todo separado por un divisor fino de 40px. Cada sección se renderiza de forma condicional, así que solo incluyes lo que necesitas.
Anatomía
Un elemento `<footer>` envuelve un div contenedor centrado (max-width desde `--container-max-width`, padding desde `--container-padding-x`). Dentro, cinco hijos apilados: un `<a>` para el nombre de marca (mayúsculas, peso 700), un `<p>` opcional para la descripción, un `<nav>` en fila flex con salto de línea para los enlaces de página, una fila flex para los enlaces sociales, una regla horizontal de 40px como un `<div>` (altura 1px, `--color-border-dark`), y un `<p>` para la línea de copyright. El espacio entre filas es de 1.5rem.
Cómo funciona
El componente es una función React puramente presentacional, sin state ni efectos. El tema se apoya por completo en propiedades CSS personalizadas (`--color-background-dark`, `--color-foreground-on-dark`, `--color-border-dark`) para adaptarse a cualquier preset sin una sola línea de JS. El hover en los enlaces se gestiona con onMouseEnter/onMouseLeave que mutan `e.currentTarget.style.color` directamente, una decisión deliberada para evitar una hoja de estilos o una dependencia de CSS modules manteniendo el bundle mínimo. El divisor de 40px entre los enlaces sociales y el copyright es un simple `<div>` que crea una pausa visual antes de la línea legal.
Cómo crearlo en React
Montar la estructura externa
Crea un `<footer>` con el background fijado en `var(--color-background-dark)` y 3rem de padding vertical. Dentro, un `div` centrado usa flexbox en columna con `alignItems: 'center'` y un gap de 1.5rem. Todos los hijos se apilan automáticamente.
<footer style={{ background: "var(--color-background-dark)", padding: "3rem 0" }}> <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: "1.5rem" }}> {/* children */} </div> </footer>Nombre de marca y descripción
Renderiza la marca como un `<a href='/'>` en mayúsculas, con font-weight 700 y letter-spacing 0.05em. Envuelve la descripción en un bloque condicional, renderízala solo cuando la cadena no esté vacía. Limítala a un max-width de 400px y baja la opacidad al 40% de blanco para que quede en segundo plano respecto a la marca.
{brandDescription && ( <p style={{ color: "rgba(255,255,255,0.4)", maxWidth: "400px", textAlign: "center" }}> {brandDescription} </p> )}Filas de navegación y sociales
Ambas filas son `display: flex` con un gap de 1.5rem y `flexWrap: 'wrap'` en la nav para que salte de línea en pantallas pequeñas. Los enlaces parten del 50% de opacidad blanca y suben al 80% en hover. Usa onMouseEnter/onMouseLeave para fijar el color directamente en `e.currentTarget.style`, sin necesidad de ninguna clase CSS.
onMouseEnter={(e) => (e.currentTarget.style.color = "rgba(255,255,255,0.8)")} onMouseLeave={(e) => (e.currentTarget.style.color = "rgba(255,255,255,0.5)")}Divisor fino y copyright
Añade un `<div>` de 40px de ancho, 1px de alto, con `background: var(--color-border-dark)` y 0.5rem de margen superior e inferior. Debajo, el `<p>` de copyright baja a 11px (0.6875rem) al 25% de opacidad blanca para que apenas se note visualmente: presente por requisitos legales, invisible a la vista.
<div style={{ width: "40px", height: "1px", background: "var(--color-border-dark)", margin: "0.5rem 0" }} /> <p style={{ fontSize: "0.6875rem", color: "rgba(255,255,255,0.25)" }}>{copyright}</p>
Cuándo usarlo
Úsalo en sitios de una sola página con tema oscuro, portfolios, páginas de agencia o landings SaaS donde el footer es un signo de puntuación final más que un hub de navegación. Funciona mejor cuando la página ya tiene una identidad visual fuerte y el footer solo necesita cerrar con limpieza. Evítalo cuando necesites grupos de enlaces en varias columnas, suscripción a una newsletter o secciones legales extensas: el layout de una sola columna no tiene la densidad necesaria.
Usado por
- Stripe, Usa footers oscuros centrados con filas de enlaces minimalistas en sus páginas de campaña y landings de producto.
- Loom, Footer oscuro con marca, una fila de navegación plana y una línea de copyright discreta en sus páginas de marketing.
- Framer, Footer centrado minimalista en las landings de producto, marca en primer lugar con enlaces en una única fila.
FAQ
¿Puedo añadir una imagen de logo en lugar del nombre de marca en texto?
Sustituye el nodo de texto del `<a>` por un `<img>` o un componente SVG inline. Mantén el envoltorio anchor para que el logo siga siendo un enlace a la home; ajusta el ancho al que encaje con tu marca.
¿Cómo cambio el color de hover de los enlaces de blanco a un color de acento?
En el handler onMouseEnter, cambia `rgba(255,255,255,0.8)` por tu valor de acento, por ejemplo `var(--color-accent)`. Haz lo mismo para el reset en onMouseLeave. No se necesita ninguna clase CSS ni state adicional.
¿Es accesible este footer para usuarios de teclado y lectores de pantalla?
El componente usa un elemento `<footer>` semántico y etiquetas `<a>` nativas, así que la navegación por teclado y los lectores de pantalla funcionan sin ARIA adicional. El texto de copyright de baja opacidad puede no superar el contraste WCAG AA; añade un `aria-label` con el texto completo si la conformidad legal lo exige.
¿Por qué los estilos de hover se gestionan con JS inline en lugar de una clase CSS?
El componente usa estilos inline en todas partes para mantenerse autónomo y evitar una dependencia de CSS modules o de una hoja de estilos global. El patrón onMouseEnter/onMouseLeave es el compromiso pragmático para un componente simple y aislado. Si tu proyecto usa Tailwind, sustituir los estilos inline por clases utilitarias y el variant `hover:` es sencillo.