- Critical CSS es la cantidad mínima de CSS necesaria para renderizar la parte visible al inicio de la página (above the fold); al insertarlo en línea dentro del HTML, mejora Core Web Vitals como el FCP (First Contentful Paint)
- Se inserta en línea dentro del
<head> del HTML para que el navegador pueda renderizar el contenido rápidamente sin esperar a toda la hoja de estilos
- Ofrece ventajas como mejor percepción de velocidad de carga inicial, aumento del puntaje de Lighthouse y mejoras en SEO y UX
- El CSS no esencial puede cargarse con un
<link> al final del <body> o mediante carga diferida con JavaScript para optimizar aún más el rendimiento
- Hay que tener en cuenta que el usuario debe ajustar manualmente las rutas de los enlaces CSS y las referencias a recursos
Critical CSS Generator
- Critical CSS Generator es una herramienta que extrae solo el código CSS mínimo e indispensable de una página web, permitiendo una extracción optimizada según el caso de uso
- Critical CSS son las reglas CSS mínimas necesarias para dar estilo al área visible inicialmente de la página
- Este enfoque ayuda a mejorar el rendimiento y Core Web Vitals (como FCP), ya que permite al navegador mostrar de inmediato el contenido principal sin esperar a que carguen todas las hojas de estilo
¿Por qué usarlo?
- Mayor velocidad percibida en la carga inicial
- Mejora del puntaje de Lighthouse
- Mejor SEO y experiencia de usuario
🔧 Cómo aplicarlo
Step 1: Insertar Critical CSS en línea
Step 2: Carga diferida del CSS no esencial (método básico)
Step 3 (opcional): Carga asíncrona de estilos con JavaScript
- Después de que termine de cargar la página, usa JavaScript para cargar dinámicamente el CSS no esencial
- Puede mejorar el rendimiento cuando la velocidad de red es baja
- Deben eliminarse del
<head> todos los <link> de CSS no esencial existentes
window.addEventListener("DOMContentLoaded", function () {
console.log("✅ Page loaded, now loading non-critical stylesheets...");
let stylesheets = [
// "/css/vendors.min.css",
// "/css/style.min.css",
];
let loadedCount = 0;
function checkAllStylesLoaded() {
loadedCount++;
if (loadedCount === stylesheets.length) {
console.log("✅ All non-critical stylesheets loaded...");
}
}
stylesheets.forEach(function (href) {
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = href;
link.onload = checkAllStylesLoaded;
link.onerror = () => console.warn(`Failed to load stylesheet: ${href}`);
document.head.appendChild(link);
});
});
1 comentarios
Comentarios en Hacker News
Se vería genial si también soportara diseño responsivo; como es difícil deduplicar estilos críticos responsivos, al final siempre he seguido editando las hojas de estilo a mano. Ya que el tamaño del CSS crítico importa, también estaría bien una opción para hacer down-compile de cosas como variables CSS. Y no recomendaría el consejo de poner la etiqueta
<link>del CSS no crítico antes de</body>; el CSS debe recibirse rápido, así que este método retrasa el descubrimiento del CSS y por tanto también su descarga. En cambio, recomiendo un método que combinepreloadynoscript:<link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'"><noscript><link rel="stylesheet" href="styles.css"></noscript>Me pregunto si este método de usar código JS en ese
preloadno quedará bloqueado si la CSP no permiteunsafe-inlineNo quiero usar una forma de cargar CSS mediante hacks de JS; al aplicar la hoja de estilos puede recalcularse el layout/estilo de toda la página. El navegador descarga rápidamente la hoja de estilos incluso si está al final de la página.
Con solo la combinación de
prefetch, hints por headers HTTP y un CDN también se puede lograr un efecto parecido; no hace falta reconstruir continuamente el CSS crítico. Si usas bien un CDN como CF, va rapidísimo.Creo que tienes razón, también planeo agregar una opción así. En lugar de
before body, probé una opciónDOMContentLoaded, y hasta en teléfonos viejos o redes lentas funciona suficientemente bien para UX y Lighthouse.Totalmente de acuerdo con lo del soporte responsivo.
En mi opinión esto se siente como una optimización prematura. Puede tener valor si el CSS es extremadamente complejo o si se cargan muchísimos recursos, pero en la mayoría de los casos es más eficiente escribir CSS, HTML y JS de forma limpia, y este enfoque puede ser innecesario o incluso perjudicial.
Es súper útil; como freelancer a menudo trabajo en sitios de WordPress, y muchas veces el CSS/JS termina hecho un desastre después de pasar por varios desarrolladores/agencias. De verdad quiero probar una herramienta así.
Cuanto más complejo sea el CSS o cuantos más recursos haya, menor suele ser el beneficio neto de esta optimización. Lo que se busca aquí es optimizar la latencia RTT, y mientras más grande sea el CSS crítico, mayor es el costo de la optimización, así que la ganancia neta disminuye.
Hace 12 años habría pagado por una herramienta así. Teníamos cantidades enormes de CSS acumulado durante años, y era difícil saber qué reglas eran críticas.
Para muchos sitios definitivamente puede ser una optimización prematura. Pero en sitios sensibles al clic, como noticias o medios, una carga de página “instantánea” es muy importante; si pasa apenas 1 segundo, bajan la retención y los ingresos por publicidad. HuffPost también probó esta optimización hace 10 años.
Viendo el estado actual del desarrollo frontend, de verdad se siente excesivo. Herramientas como Lighthouse han hecho que la gente se obsesione con optimizar para números sin sentido; como resultado, solo aumenta la complejidad del build, el usuario real ni lo percibe y desarrollar se vuelve más incómodo. Mientras tanto, todavía veo a menudo sitios llenos de errores básicos de UI/gestión de estado. Es frustrante.
La respuesta sí es CSS, HTML y JS limpios, pero a veces te toca heredar proyectos desordenados o usar plantillas, y aun desarrollando yo mismo se me puede enredar el diseño.
Para mí, la forma de cargar CSS es algo que hay que considerar sí o sí desde la primera etapa del desarrollo. Tuvimos muchos casos de clientes que se iban porque nuestro sitio sacaba mala puntuación en page speed tests. Como el rendimiento afecta al SEO, es muy importante. Rediseñé personalmente la optimización de páginas para sacar 100 puntos en Google Lighthouse; hay que planear desde el inicio incluso el orden y la forma de cargar CSS/JS para reducir retrabajo después. Nosotros dividimos el CSS por encima y por debajo del fold y lo incluimos inline donde correspondía; el JS por debajo del fold ni siquiera se evalúa hasta que se hace scroll. Aplicamos todo lo que sugería Lighthouse. El sistema anterior cargaba en todas las páginas todo el CSS del sitio (3~4MB), y el JS era todavía peor; fue por no haber diseñado la optimización desde el principio. Seguimos usando ese sistema, así que no puedo decir el nombre, pero internamente sigue siendo un problema. Si el objetivo es el rendimiento, no creo que exista el concepto de optimización prematura: hay que considerar todo desde el inicio. Como resultado, obtenemos 100 de rendimiento para todos los clientes, incluyendo móviles, y tenemos ventaja frente a la competencia. Probé esta herramienta en mi sitio y ya tenía todo tan optimizado que no hubo efecto.
En mi página hecha con Astro, el HTML es 27.52KB (6.1KB comprimido), el JS es menos de 10KB y el CSS crítico 57KB (7KB comprimido). Sitios parecidos van de 100KB a 1MB. Si construyes limpio, con resource hints basta para que sea rápido incluso sin inline css/js. Con una combinación de nginx+HTTP/2+edge cache se puede lograr 100/100 de rendimiento sin CSS crítico ni JS inline. No sé si tenga sentido agregar 7KB extra por página; en implementación, SPA/edge caching es mucho más ecológico y rápido. No hay necesidad de enviar HTML exageradamente pesado como con Elementor, y la batería del móvil es limitada como para enviar datos innecesarios.
Es un buen truco, pero en una situación donde CDN y HTTP/2 ya son comunes, este tipo de optimización al final solo desperdicia ancho de banda. Apenas mejora un poco los números de benchmark, y en la práctica solo acelera unos 10~20ms.
Incluir CSS crítico en todas las páginas no siempre es la respuesta. Usarlo selectivamente solo en la primera visita (sin caché) o en la página inicial de una sesión también puede evitar data bloat innecesario.
Busqué una herramienta para extraer CSS crítico por pedido de un cliente, pero como no encontré lo que quería, terminé compartiendo una solución propia hecha con Puppeteer. Se puede indicar cuánto esperar después de cargar la página. También probé servicios de pago, pero no me gustaron y pedí reembolso. Agradezco el feedback; por ahora lo abrí gratis.
Me da curiosidad si el problema era con herramientas existentes como el paquete penthouse.
Si ingresas un sitio sin CSS, aparece un error.
¿El código está publicado? También me gustaría usarlo como plugin de Vite/Astro.
Quisiera preguntar si es una versión con UI de penthouse; muchos valores de configuración se parecen bastante.
Este método más bien produce el efecto contrario. Genera un FOUC (parpadeo de contenido sin estilos) muy consistente; si el layout cambia a mitad de la interacción, un usuario que ya estaba haciendo clic puede sufrir una molestia importante. No es solo un problema visual, sino de usabilidad real.
Yo también ajusté algunos estilos después de aplicar este método, pero al final sí pude optimizar hasta lograr CLS (cumulative layout shift) 0. Cuando tienes poco presupuesto y usas plantillas con muchas librerías, puede ser muy útil.
¿No se supone que el objetivo original es evitar el FOUC sin bloquear el
network requestdel CSS?Este enfoque tiene más sentido bajo la suposición de que en la primera vista de la página no hay absolutamente nada de caché CSS. En la práctica, hay trade-offs entre varios factores: proporción de usuarios nuevos/recurrentes, configuración de caché CSS, CDN, 103 early hints, CSS crítico/initial congestion window, etc.
Al medir rendimiento en localhost, la influencia del CSS era casi nula. Incluso eliminando por completo el CSS, la mejora era menor a 7ms, y eso ya entra dentro del margen de error de la medición.
Al usar esta herramienta en mi sitio, se extrajo al CSS incluso contenido de debugging que no era estrictamente necesario; por ejemplo,
body::afterpara un overlay de cuadrícula del sitio también quedó incluido tal cual (ni me acordaba de eso hasta que lo descubrí ahora).Prefiero escribir HTML que comunique bien el significado incluso sin CSS. Así puedes evitar desde antes que la estructura del documento se vuelva demasiado compleja.
La idea en sí me pareció fresca y la probé en mi sitio personal, pero en la librería penthouse ocurrió un error de omisión de CSS:
{"error":true,"name":"Error","message":"css should not be empty" ...}