Dominá next/font: Cargá fuentes de Google o locales sin arruinar tu CLS

DUGLAS MORENODUGLAS MORENO 👁 7

Seguramente te pasó: entrás a una web, el texto aparece con una tipografía genérica tipo Arial durante un segundo, y de golpe —¡pum!— la fuente cambia a la que el diseñador eligió. Ese salto visual es molesto para el usuario y, lo que es peor, es un pecado capital para el SEO. Estamos hablando del Cumulative Layout Shift (CLS), una de las métricas de Core Web Vitals que Google usa para decidir si tu sitio es rápido y estable o si es un desastre.

En este artículo, vamos a meternos de lleno en next/font, la solución oficial de Next.js para gestionar la tipografía de forma inteligente. Vas a aprender a configurar Google Fonts y fuentes locales para que la carga sea invisible para el ojo humano y perfecta para los motores de búsqueda.

¿Por qué el cambio de fuente rompe tu web?

El problema técnico se llama FOUT (Flash of Unstyled Text). Cuando el navegador descarga tu HTML, empieza a renderizar el texto usando la fuente del sistema (la que tenga por defecto). Cuando la fuente externa (Google Fonts, por ejemplo) termina de descargarse, el navegador tiene que volver a calcular el tamaño, el ancho y el interlineado de cada letra. Si la nueva fuente es más ancha o más alta, todo el contenido de la página se desplaza.

next/font soluciona esto de dos maneras:

  1. Autohospedaje automático: Si usás Google Fonts, Next.js descarga los archivos de fuente en tiempo de compilación y los sirve desde tu propio dominio. No hay peticiones extra a los servidores de Google durante la carga del cliente.
  2. Ajuste de tamaño (Size Adjust): Genera automáticamente reglas CSS para que la fuente de respaldo (fallback) tenga un tamaño casi idéntico al de la fuente principal, minimizando el salto visual.

Configurando Google Fonts con next/font/google

Esta es la forma más común. Ya no necesitás importar un link en el <head> de tu layout.js. Ahora lo hacés mediante un módulo de Next.js.

Paso 1: Importación y configuración

Supongamos que querés usar la fuente Inter, que es un estándar de la industria por su legibilidad.

// app/layout.js
import { Inter } from 'next/font/google';

// Configuramos la fuente
const inter = Inter({ 
  subsets: ['latin'], 
  display: 'swap', // Esto es clave para el rendimiento
  variable: '--font-inter' // Usamos una variable CSS para mayor flexibilidad
});

export default function RootLayout({ children }) {
  return (
    <html lang="es" className={inter.variable}>
      <body className={inter.className}>
        {children}
      </body>
    </html>
  );
}

Detalles que tenés que saber:

  • subsets: Es obligatorio. Te permite descargar solo los caracteres que necesitás (ej: ['latin']), lo que reduce drásticamente el peso del archivo.
  • display: 'swap': Le dice al navegador: "Mostrá la fuente de sistema primero y, cuando la real esté lista, hacé el cambio". Gracias al motor de Next.js, este cambio será casi imperceptible.
  • variable: Al definir una variable CSS, podés usarla en tus archivos de Tailwind CSS o CSS Modules sin tener que inyectar clases en cada elemento.

Cómo usar fuentes locales con next/font/local

A veces no te alcanza con Google. Quizás tenés una fuente comprada o una tipografía exclusiva de tu marca en archivos .woff2. Para esto usamos next/font/local.

Estructura de archivos recomendada

Primero, asegurate de tener tus archivos en una carpeta dedicada, por ejemplo public/fonts/ o dentro de app/fonts/.

mi-proyecto/
├── app/
│   ├── fonts/
│   │   ├── MiFuente-Regular.woff2
│   │   └── MiFuente-Bold.woff2
│   └── layout.js

Implementación

// app/layout.js
import localFont from 'next/font/local';

const miFuenteLocal = localFont({
  src: [
    { 
      path: './fonts/MiFuente-Regular.woff2', 
      weight: '400', 
      style: 'normal' 
    },
    { 
      path: './fonts/MiFuente-Bold.woff2', 
      weight: '700', 
      style: 'normal' 
    },
  ],
  variable: '--font-local',
});

export default function RootLayout({ children }) {
  return (
    <html lang="es" className={miFuenteLocal.variable}>
      <body className={miFuenteLocal.className}>
        {children}
      </body>
    </html>
  );
}

Integración con Tailwind CSS

Si usás Tailwind, la configuración de variable que hicimos arriba es tu mejor amiga. No necesitás andar pegando clases de fuentes en cada <h1> o <p>.

  1. Agregá la variable a tu tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      fontFamily: {
        // Acá mapeás la variable CSS que definimos en el layout
        sans: ['var(--font-inter)', 'sans-serif'],
        custom: ['var(--font-local)', 'serif'],
      },
    },
  },
  plugins: [],
}
  1. Ahora, en tus componentes, simplemente usás las clases de Tailwind:
export default function Hero() {
  return (
    <section className="p-10">
      <h1 className="font-custom text-4xl font-bold">Este título usa la fuente local</h1>
      <p className="font-sans text-lg">Este párrafo usa Inter desde Google Fonts.</p>
    </section>
  );
}

Comparativa: ¿Qué pasa por detrás?

Para que entiendas la magia, veamos una simulación de cómo el navegador procesa la carga. Aunque no podemos ver el motor de renderizado de Next.js directamente, podemos simular la lógica de qué pesos y estilos se están inyectando.

// Simulamos la lógica de inyección de estilos que hace Next.js
const fontConfig = {
  name: "Inter",
  subsets: ["latin"],
  display: "swap",
  fallback: "ui-sans-serif, system-ui, sans-serif"
};

function simulateFontLoading(config) {
  console.log(`--- Iniciando carga de fuente: ${config.name} ---`);
  console.log(`1. Cargando subsets: ${config.subsets.join(', ')}`);
  console.log(`2. Aplicando estrategia de visualización: ${config.display}`);
  console.log(`3. Generando fallback con ajuste de tamaño (size-adjust) para evitar CLS...`);
  
  // Simulamos el CSS que Next.js inyecta para que el fallback no salte
  const injectedCSS = `
@font-face {
  font-family: '${config.name} fallback';
  src: local('${config.fallback}');
  size-adjust: 95%; /* Esto reduce el tamaño del fallback para que coincida con la real */
  ascent-override: 90%;
}
  `;
  
  console.log("CSS Inyectado preventivamente:");
  console.log(injectedCSS);
  console.log("--- Carga completada: El CLS será mínimo ---");
}

simulateFontLoading(fontConfig);

Salida esperada del código anterior:

--- Iniciando carga de fuente: Inter ---
1. Cargando subsets: latin
2. Aplicando estrategia de visualización: swap
3. Generando fallback con ajuste de tamaño (size-adjust) para evitar CLS...
CSS Inyectado preventivamente:

@font-face {
  font-family: 'Inter fallback';
  src: local('ui-sans-serif, system-ui, sans-serif');
  size-adjust: 95%; /* Esto reduce el tamaño del fallback para que coincida con la real */
  ascent-override: 90%;
}
  
--- Carga completada: El CLS será mínimo ---

Buenas prácticas y errores comunes

Para no mandarte macanas, tené en cuenta estos puntos:

✅ Qué SI hacer:

  • Usar .woff2 siempre que sea posible: Es el formato de fuente más comprimido y eficiente actualmente.
  • Limitar los pesos (weights): No cargues 400, 500, 600, 700 y 900 si solo vas a usar 400 y 700. Cada peso es un archivo extra que el usuario tiene que bajar.
  • Definir subsets específicos: Si tu web es solo en español, no necesitás el subset de caracteres cirílicos o griegos.

❌ Qué NO hacer:

  • No uses next/font para fuentes que cambian dinámicamente por el usuario: next/font está diseñado para fuentes estáticas que forman parte de tu diseño. Si necesitás fuentes que el usuario elija (como en un editor de texto), usá una carga dinámica convencional.
  • No olvides el display: 'swap': Si no lo ponés, podrías experimentar el efecto de "texto invisible" mientras la fuente carga (FOIT - Flash of Invisible Text), lo cual es igual de malo para la experiencia de usuario.
  • No sobrecargues el layout: Evitá declarar 10 fuentes distintas en el layout.js. Cada fuente añade latencia. Mantené la sobriedad.

Conclusión

Implementar next/font no es solo una cuestión de estética, es una decisión de ingeniería. Al usar este módulo, estás automatizando tareas complejas como el self-hosting, la optimización de subsets y, lo más importante, el cálculo de compensación de tamaño para evitar el CLS.

Resumen de pasos para tu próximo proyecto:

  1. Elegí tus fuentes (Google o locales).
  2. Configurá el objeto de fuente en tu layout.js usando next/font/google o next/font/local.
  3. Definí una variable CSS para mantener el código limpio.
  4. Mapeá esa variable en tu configuración de Tailwind.
  5. ¡Disfrutá de una web rápida, estable y con un puntaje de Core Web Vitals por las nubes!

Si te sirvió este tutorial, ¡compartilo con algún colega que todavía esté pegando links de Google Fonts en el HTML!

Comentarios (0)

Sé el primero en comentar.

Dejá tu comentario