Next.js Dark Mode

Guía Next.js: Modo Oscuro sin parpadeos (Flash of Unstyled Content)

¿Alguna vez has entrado en una web con modo oscuro activado y, por una fracción de segundo, te ha cegado un fogonazo blanco antes de cargar el tema? Ese fenómeno se conoce como FOUC (Flash of Unstyled Content) y es el síntoma más común de una implementación deficiente en aplicaciones React modernas.

En pleno 2026, la experiencia de usuario (UX) no perdona estos errores técnicos. Con el auge de las pantallas OLED y la navegación nocturna, el soporte nativo para el esquema de color del sistema no es una opción, es un estándar de accesibilidad. Si tu aplicación de Next.js parpadea al recargar, estás perdiendo retención de usuarios y profesionalismo.

Hoy te enseñaré la metodología definitiva que utilizamos en AndroFan para nuestras aplicaciones internas. Olvida los hacks de `localStorage` manuales que fallan en el servidor; vamos a implementar una solución robusta utilizando Server Components, Tailwind CSS y la librería next-themes, optimizada para las últimas versiones de Next.js.

Por qué ocurre el parpadeo en Next.js

El problema reside en el Hydration mismatch. Cuando usas Next.js, el servidor genera el HTML inicial. Si el servidor no sabe qué tema prefiere el usuario (porque el servidor no tiene acceso al `localStorage` del navegador), enviará el tema por defecto, que suele ser el claro.

Una vez que el JavaScript se ejecuta en el cliente, el navegador lee la preferencia y cambia el estilo, provocando ese destello blanco de 200ms a 500ms.

Para solucionar esto en 2026, necesitamos inyectar un script de bloqueo antes de que el navegador renderice el cuerpo de la página. Este script debe ejecutarse de forma síncrona para determinar la clase `dark` antes de que el usuario vea el primer píxel.

Instalación y Configuración del Tema

Para esta guía utilizaremos el stack estándar de la industria: Tailwind CSS v4 (o v3.4+) y la biblioteca next-themes, que ya gestiona la inyección del script de bloqueo por nosotros.

  1. Instala la dependencia principal: npm install next-themes.
  2. Configura tu archivo tailwind.config.js para soportar el cambio por clase:
module.exports = {
  darkMode: ‘class’,
  content: [/* tus rutas */],
  theme: { extend: {} },
}

Diferencias entre estrategias de detección

EstrategiaVelocidadComplejidad
Class StrategyInstantáneaBaja
Media QueryAutomáticaNula
Data AttributeInstantáneaMedia

Implementación del ThemeProvider en App Router

En Next.js 14/15, el archivo `layout.tsx` es un Server Component por defecto. No podemos añadir el proveedor directamente allí si requiere contexto de cliente. Debemos crear un componente envoltorio.

  1. Crea un archivo llamado providers.tsx en tu carpeta de componentes.
  2. Añade la directiva 'use client' al inicio.
  3. Envuelve los children con el ThemeProvider.
💡 Consejo Pro: Asegúrate de pasar el atributo enableSystem={true}. En 2026, los usuarios esperan que la web cambie automáticamente si su sistema operativo activa el modo noche programado.

Luego, en tu `app/layout.tsx`, importa este componente y envuelve el cuerpo de tu aplicación. Es crucial que el `ThemeProvider` esté lo más arriba posible en el árbol de componentes para evitar retrasos en la propagación de estilos.

Creación del Switch de Tema sin errores de hidratación

Uno de los errores más frustrantes es el Hydration Error (el cliente renderiza algo distinto al servidor). Esto ocurre si intentas mostrar un icono de sol o luna basándote en el tema actual inmediatamente.

Para evitarlo, debemos esperar a que el componente se monte utilizando un hook de efecto:

  • Usa useState y useEffect para verificar si el componente está montado.
  • Si mounted es falso, devuelve un placeholder o null.
  • Usa useTheme de next-themes para cambiar entre ‘dark’, ‘light’ o ‘system’.
⚠️ Importante: No intentes forzar el modo oscuro solo con CSS media queries si quieres dar al usuario un botón de control manual. La persistencia en localStorage es vital para la consistencia.

Ventajas y Desventajas

✅ Ventajas

  • Eliminación total del parpadeo blanco (FOUC).
  • Sincronización perfecta con las preferencias del sistema.
  • Optimizado para Core Web Vitals y SEO.

❌ Desventajas

  • Requiere una pequeña carga adicional de JS en el cliente (mínima).
  • Configuración inicial ligeramente más compleja que el CSS puro.

Preguntas Frecuentes

¿Puedo usar esto con Vanilla CSS?

Sí, next-themes funciona inyectando una clase en el elemento HTML. Puedes definir tus variables CSS dentro de un selector .dark en tu archivo global.

¿Afecta al rendimiento LCP?

Al contrario. Al evitar el parpadeo y los cambios de layout bruscos, tus métricas de Cumulative Layout Shift (CLS) mejorarán considerablemente.

¿Funciona con el nuevo React Server Components?

Totalmente. El proveedor es un Client Component, pero puede envolver Server Components sin problemas, permitiéndote mantener la velocidad de renderizado de Next.js.

Conclusión

  • El parpadeo ocurre por la falta de sincronía entre el servidor y el cliente.
  • Usar next-themes es la forma más eficiente de inyectar el script de bloqueo necesario.
  • Siempre valida el montaje del componente para evitar errores de hidratación en el switch.

Lograr una interfaz pulida requiere atención al detalle. Con esta guía, tus usuarios disfrutarán de una transición suave y profesional entre temas. ¿Has tenido problemas con el modo oscuro en tus proyectos? ¡Cuéntanos tu experiencia en los comentarios!

Comentarios

Aún no hay comentarios. ¿Por qué no comienzas el debate?

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *