Optimización de Fuentes
Auto-aloja y optimiza fuentes web con next/font -- sin desplazamiento de diseño, sin solicitudes de red externas, subsetting automático.
Busca en todas las páginas de la documentación
Auto-aloja y optimiza fuentes web con next/font -- sin desplazamiento de diseño, sin solicitudes de red externas, subsetting automático.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Tarjeta de receta de referencia rápida -- lista para copiar y pegar.
// app/layout.tsx
import { Inter } from "next/font/google";
const inter = Inter({
subsets: ["latin"],
display: "swap",
});
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={inter.className}>
<body>{children}</body>
</html>
);
}// Fuente variable con variable CSS
const inter = Inter({
subsets: ["latin"],
variable: "--font-inter",
});
// Usa en Tailwind CSS
<html className={inter.variable}>
// tailwind.config.ts: fontFamily: { sans: ["var(--font-inter)"] }Cuándo usarlo: Cada proyecto de Next.js que usa fuentes personalizadas. next/font elimina FOUT (flash of unstyled text), auto-aloja los archivos de fuente, y requiere cero solicitudes de red externas.
// app/layout.tsx -- múltiples fuentes con variables CSS
import { Inter, JetBrains_Mono } from "next/font/google";
const inter = Inter({
subsets: ["latin"],
variable: "--font-sans",
display: "swap",
});
const jetbrainsMono = JetBrains_Mono({
subsets: ["latin"],
variable: "--font-mono",
display: "swap",
});
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" className={`${inter.variable} ${jetbrainsMono.variable}`}>
<body className="font-sans antialiased">{children}</body>
</html>
);
}// tailwind.config.ts
import type { Config } from "tailwindcss";
const config: Config = {
theme: {
extend: {
fontFamily: {
sans: ["var(--font-sans)", "system-ui", "sans-serif"],
mono: ["var(--font-mono)", "Menlo", "monospace"],
},
},
},
};
export default config;// app/components/code-block.tsx
export function CodeBlock({ code }: { code: string }) {
return (
<pre className="font-mono bg-gray-900 text-green-400 p-4 rounded overflow-x-auto">
<code>{code}</code>
</pre>
);
}// Usando una fuente personalizada local
// app/fonts.ts
import localFont from "next/font/local";
export const calSans = localFont({
src: [
{
path: "../public/fonts/CalSans-Regular.woff2",
weight: "400",
style: "normal",
},
{
path: "../public/fonts/CalSans-Bold.woff2",
weight: "700",
style: "normal",
},
],
variable: "--font-cal",
display: "swap",
});// app/layout.tsx -- combinando fuentes de Google y locales
import { Inter } from "next/font/google";
import { calSans } from "./fonts";
const inter = Inter({ subsets: ["latin"], variable: "--font-sans" });
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en" className={`${inter.variable} ${calSans.variable}`}>
<body className="font-sans">
{children}
</body>
</html>
);
}Lo que esto demuestra:
display: "swap" para carga accesible de fuentesnext/font descarga archivos de fuente en tiempo de compilación y los auto-aloja junto a tus assets estáticos. El navegador no realiza solicitudes a Google Fonts (ni a ningún CDN externo) en tiempo de ejecución.Cache-Control: public, immutable, max-age=31536000 para almacenamiento en caché óptimo.next/font genera automáticamente declaraciones @font-face con los valores correctos de font-display, unicode-range, y src.variable, se establece una propiedad personalizada CSS (por ejemplo, --font-sans) en el elemento donde aplicas la clase. Esto se integra limpiamente con la configuración fontFamily de Tailwind CSS.subsets restringe qué rangos de caracteres se incluyen, reduciendo el tamaño del archivo. Para idiomas de escritura latina, ["latin"] suele ser suficiente.Pesos de fuente específicos (fuentes no variables):
import { Roboto } from "next/font/google";
const roboto = Roboto({
weight: ["400", "500", "700"],
subsets: ["latin"],
display: "swap",
});Fuente con múltiples subsets:
const notoSans = Noto_Sans({
subsets: ["latin", "latin-ext", "cyrillic"],
display: "swap",
});Precarga de una fuente específica:
// next/font precarga automáticamente las fuentes usadas en el layout raíz.
// Para fuentes usadas solo en páginas específicas, impórtalas en el layout de esa página.
// app/blog/layout.tsx
import { Merriweather } from "next/font/google";
const merriweather = Merriweather({
weight: ["400", "700"],
subsets: ["latin"],
variable: "--font-serif",
});
export default function BlogLayout({ children }: { children: React.ReactNode }) {
return <div className={merriweather.variable}>{children}</div>;
}Métricas de fallback de fuente (size-adjust):
// next/font calcula automáticamente size-adjust, ascent-override,
// descent-override, y line-gap-override para la fuente de fallback para
// minimizar CLS. No se necesita configuración manual.
const inter = Inter({
subsets: ["latin"],
display: "swap",
adjustFontFallback: true, // default -- genera métricas de fallback coincidentes
});import type { NextFont } from "next/dist/compiled/@next/font";
// Las funciones next/font devuelven un objeto NextFont
const inter: NextFont = Inter({ subsets: ["latin"] });
// Propiedades clave
inter.className; // string -- clase CSS que aplica la fuente
inter.variable; // string | undefined -- clase de variable CSS (si se usa la opción variable)
inter.style; // { fontFamily: string; fontWeight?: number; fontStyle?: string }
// Tipo de fuente local source
import localFont from "next/font/local";
const myFont = localFont({
src: [
{ path: "./font-regular.woff2", weight: "400", style: "normal" },
{ path: "./font-bold.woff2", weight: "700", style: "normal" },
{ path: "./font-italic.woff2", weight: "400", style: "italic" },
],
});Fuente no aplicándose -- Olvidar agregar la clase className o variable a un elemento padre significa que la fuente nunca se activa. Solución: Aplica inter.className (o inter.variable) a <html>, <body>, o el contenedor relevante.
Fuentes variables con pesos explícitos -- Algunas fuentes de Google Fonts están disponibles como fuentes variables pero pasas pesos específicos de todos modos, causando que Next.js descargue archivos de fuente estática separados. Solución: Omite la opción weight para fuentes variables para obtener el archivo de fuente variable único.
Múltiples subsets aumentan el tamaño del bundle -- Cada subset se suma al tamaño del archivo de fuente. Solución: Solo incluye los subsets que tu contenido realmente usa.
display: "optional" puede causar texto invisible -- Con font-display: optional, el navegador puede saltarse la fuente personalizada completamente si no carga lo suficientemente rápido (dentro de ~100ms). Solución: Usa display: "swap" para la mayoría de casos para garantizar que la fuente personalizada eventualmente se muestre.
Parpadeo de fuente en navegación cliente -- Si una fuente se carga en un layout específico de página (no el layout raíz), puede parpadear durante la navegación del lado del cliente a esa página. Solución: Carga las fuentes de uso frecuente en el layout raíz para que siempre estén disponibles.
next/font solo funciona en Server Components -- No puedes llamar a Inter() o localFont() dentro de un archivo "use client". Solución: Define fuentes en un Server Component (como layout.tsx o un archivo dedicado fonts.ts) y aplica las clases mediante el DOM.
| Alternativa | Usa Cuando | No Uses Cuando |
|---|---|---|
next/font/google | Quieres fuentes de Google auto-alojadas con cero configuración | Usas una fuente propietaria no en Google Fonts |
next/font/local | Tienes archivos de fuente personalizados (woff2, ttf, otf) | La fuente está disponible en Google Fonts |
CDN de Google Fonts (<link>) | Nunca en Next.js -- next/font es estrictamente mejor | -- |
| Stack de fuentes del sistema | Quieres máximo rendimiento con cero descargas de fuente | Las directrices de marca requieren un typeface específico |
| Fontsource (paquetes npm) | Quieres paquetes de fuentes gestionados por npm fuera de Next.js | next/font ya maneja auto-alojamiento |
@font-face.Usa la opción variable para crear una propiedad personalizada CSS, luego refiérala en tailwind.config.ts:
const inter = Inter({ subsets: ["latin"], variable: "--font-sans" });
// tailwind.config.ts
fontFamily: { sans: ["var(--font-sans)", "system-ui"] }Aplica inter.variable como clase en <html>.
import localFont from "next/font/local";
const myFont = localFont({
src: [
{ path: "./font-regular.woff2", weight: "400" },
{ path: "./font-bold.woff2", weight: "700" },
],
variable: "--font-custom",
});className aplica la fuente directamente mediante una clase CSS con una regla font-family.variable establece una propiedad personalizada CSS (por ejemplo, --font-sans) que puedes referenciar en CSS o en la configuración de Tailwind. Usa variable cuando integres con Tailwind.Probablemente olvidaste agregar inter.className o inter.variable como clase en un elemento padre (por ejemplo, <html> o <body>). La fuente no se activa sin que la clase se aplique al DOM.
Pasar valores de weight explícitos para una fuente que soporta pesos variables causa que Next.js descargue archivos de fuente estática separados en lugar de un archivo de fuente variable único. Omite la opción weight para obtener el archivo de fuente variable único.
No. Las funciones next/font (Inter(), localFont()) solo se pueden llamar en Server Components. Define fuentes en layout.tsx o un archivo dedicado fonts.ts (sin "use client") y aplica las clases mediante el DOM.
"swap": muestra una fuente fallback inmediatamente, luego cambia a la fuente personalizada una vez cargada. Garantiza que la fuente personalizada eventualmente aparezca."optional": el navegador puede saltarse la fuente personalizada completamente si no carga dentro de ~100ms. Puede causar texto personalizado invisible o faltante.Importa la fuente en un layout anidado en lugar del layout raíz:
// app/blog/layout.tsx
import { Merriweather } from "next/font/google";
const merriweather = Merriweather({ weight: ["400"], subsets: ["latin"], variable: "--font-serif" });
export default function BlogLayout({ children }) {
return <div className={merriweather.variable}>{children}</div>;
}import type { NextFont } from "next/dist/compiled/@next/font";
const inter: NextFont = Inter({ subsets: ["latin"] });
// Propiedades: inter.className, inter.variable, inter.styleCada entrada es un objeto con path (string), weight (string), y opcionalmente style (string):
const myFont = localFont({
src: [
{ path: "./font-regular.woff2", weight: "400", style: "normal" },
{ path: "./font-italic.woff2", weight: "400", style: "italic" },
],
});Cada subset y archivo de fuente se suma a la salida de compilación. Solo incluye los subsets que tu contenido usa y limita el número de familias de fuente a lo que tu diseño requiere.
Revisado por Chris St. John·Última actualización: 19 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥