¿Por qué mi critical CSS rompió mi menú / superposición (aparece abierto al cargar)?
El resumen en una frase: los generadores de critical CSS solo conservan los estilos de lo que es visible en la parte superior de la página al cargar. Sus elementos ocultos por defecto y que se abren al hacer clic (menú móvil, superposición de búsqueda, modal, panel lateral) se consideran inútiles y se eliminan. El resultado: al cargar, aparecen abiertos, rotos, sin estilo.
Activa el critical CSS (que solo inyecta los estilos para el primer renderizado) o la opción “Remove unused CSS” para ganar puntos en PageSpeed. La puntuación sube. Y de repente: su superposición de búsqueda aparece totalmente abierta al cargar, su menú móvil se despliega, un botón recupera su feo borde gris por defecto. Recarga, borra la caché… nada ayuda.
Lo más desconcertante: cuando inspecciona el código, la regla CSS está justo ahí en el HTML. Pero el navegador no la aplica. Aquí tiene la explicación completa, y la solución duradera.
Qué hace realmente un generador de critical CSS
La idea del critical CSS es legítima y eficaz: en lugar de cargar toda su hoja de estilos antes del primer renderizado (lo que bloquea la visualización), usted extrae solo el CSS necesario para la parte superior visible de la página, lo inserta en línea en el <head>, y carga el resto después (defer).
Para decidir qué es “necesario”, la herramienta renderiza la página y observa lo que es visible en el viewport en el momento de la carga. Todo lo que no es visible en ese instante se considera no crítico, o, en el modo “Remove unused CSS”, directamente inútil y eliminable.
Y ahí está la trampa.
La causa real: “oculto por defecto” = “considerado inútil”
Piense en cómo se ven sus componentes interactivos al cargar la página:
- el menú móvil: cerrado (
display:noneotransformfuera de pantalla); - la superposición de búsqueda: oculta (
opacity:0; visibility:hidden); - el modal, el drawer, el mega-menú: oculto;
- estado colapsado de las pestañas y los acordeones: contenido oculto.
Todos estos elementos son invisibles en el momento en que el generador observa la página. Este concluye, de forma lógica pero errónea, que su estilo es inútil, y lo elimina del critical CSS.
El problema: estos elementos deben aparecer después, al hacer clic, mediante JavaScript. Pero su estilo ha desaparecido. Dos síntomas clásicos:
Qué se rompe
La regla que los ocultaba ha desaparecido. Un
.overlay { opacity:0; visibility:hidden }eliminado → nada oculta ya la superposición → aparece abierta al cargar.La regla de apariencia ha desaparecido. Un
button { border:0; background:none }no conservado → el botón recupera el estilo por defecto del navegador (borde gris, relleno del sistema).
El síntoma exasperante: “la regla está ahí, pero se ignora”
Este es el punto que cuesta horas. Usted inspecciona, ve claramente .overlay { visibility:hidden } en algún lugar del HTML minificado. Entonces, ¿por qué el navegador no la aplica?
Porque en un pipeline de critical CSS, hay dos hojas de estilo:
- la crítica en línea (en el
<head>, aplicada de inmediato), despojada de sus reglas interactivas; - la hoja de estilos completa, que debe llegar de forma diferida.
Tres cosas fallan, a menudo a la vez:
- La hoja de estilos completa llega demasiado tarde (después de que el JS ya intentó abrir/cerrar el elemento), o directamente no llega en algunas rutas de renderizado.
- En el modo “Remove unused CSS”, la regla se eliminó de AMBAS hojas de estilo: ya no existe en ninguna parte.
- La cascada se vuelve en su contra: una regla presente pero menos específica (o cargada después) pierde frente al estilo en línea o por defecto.
Así que “la regla está en el HTML” no significa “la regla gana”. Puede estar presente y descartada por la cascada, o presente en una hoja que aún no se ha cargado en el momento crítico.
Las trampas del diagnóstico (por qué borrar la caché no basta)
Antes de corregir, necesita observar el renderizado real, y ahí le esperan tres trampas:
- Cachés separadas para móvil y escritorio. Muchos motores generan un critical CSS distinto para móvil y escritorio. Usted corrige, prueba en escritorio, todo bien… pero la caché móvil sigue sirviendo la versión antigua rota. Pruebe y “caliente” ambas, con el User-Agent correcto (el identificador que el navegador envía para indicar si es móvil o escritorio).
- “Borrar la caché” no siempre limpia el critical CSS por página. El crítico suele almacenarse por URL, separado de la caché HTML. Un “borrar todo” puede dejar archivos críticos obsoletos en su sitio. Debe apuntar explícitamente al CSS generado.
- El crítico se deriva de una fuente en caché. Si se regenera a partir de una versión obsoleta de su hoja de estilos de origen, su corrección nunca aparece. Debe forzar la regeneración desde la fuente actualizada.
Para ver el renderizado real sin dejarse engañar por la caché: añada un parámetro ficticio a la URL (?cb=123) para forzar un renderizado nuevo, y compare con la URL normal.
La solución duradera (y que viaja con su tema)
La tentación es poner los selectores en una “safelist” (lista de exclusión) del plugin. Eso funciona… mientras conserve ese plugin, con esa configuración. El día que cambie de herramienta o reconstruya el sitio, se rompe de nuevo.
La solución robusta y portátil consiste en sacar sus reglas verdaderamente críticas del CSS optimizable, e insertarlas usted mismo en línea de forma protegida:
a. Identifique las reglas “intocables”
- el estado oculto por defecto de cada elemento interactivo (
display:none,opacity:0; visibility:hidden…); - el reset de botones/controles (
border:0; background:none…); - el estilo completo del elemento una vez abierto (para que sea correcto desde la primera apertura);
- haga que estos componentes sean autosuficientes: un botón debe llevar su propio estilo, sin depender de una clase utilitaria que a su vez podría ser optimizada.
b. Insértelas en línea después de que se renderice el head
Coloque estas reglas en un <style> bloque después de la llamada que genera el <head> (en WordPress: después de wp_head(), normalmente en header.php). Así llegan al final y ganan la cascada sobre el crítico insertado más arriba.
c. Marque el bloque como no optimizable
Indique al motor de optimización que no lo toque. La mayoría respeta atributos dedicados:
<style data-no-optimize="1" data-no-minify="1" data-no-defer="1">
/* hidden state + button reset + full overlay style, hard-coded values */
.search-overlay { opacity: 0; visibility: hidden; /* ... */ }
.search-overlay.is-open { opacity: 1; visibility: visible; }
.search-toggle { border: 0; background: none; color: #1a1a1a; }
</style>d. Codifique los valores directamente
No use variables CSS (var(--gold)) en este bloque: si su :root en sí pasa por el optimizador, la variable puede acabar indefinida y su estilo se rompe. Codifique el color directamente.
Ventaja decisiva: esta solución vive en el tema. Funciona con el optimizador, sin el optimizador, y sobrevive a un cambio de herramienta.
Dónde marca la diferencia Mantys Core
Todo motor de critical CSS enfrenta este dilema: no puede adivinar que un elemento oculto se abrirá al hacer clic. Así que la pregunta real no es “¿ocurre esto?” (ocurre con todos ellos), sino “¿la herramienta le da palancas claras para gestionarlo?”.
Mantys Core está diseñado para esto:
respeta los bloques marcados
data-no-optimize/data-no-minify/data-no-defer(exactamente el mecanismo de la solución portátil descrita arriba) y trata su propio bloque crítico de la misma manera;le permite dirigir la regeneración del crítico página por página, desde la fuente actualizada, sin quedar atrapado por un crítico obsoleto;
y gestiona explícitamente la separación entre móvil y escritorio en lugar de dejarle adivinar qué caché sirve qué.
En otras palabras: hace el trabajo pesado de aligerar, mientras le deja control quirúrgico sobre los componentes interactivos, en lugar de eliminarlo todo y dejarle la reparación.
En resumen
- Critical CSS solo conserva el estilo de lo visible al cargar. Sus elementos ocultos por defecto (menú, superposición, modal) se consideran inútiles y se eliminan.
- Síntoma engañoso: la regla está en el HTML pero se ignora: dos hojas, una cascada que se vuelve en su contra, o una simple eliminación.
- Diagnóstico: cuidado con las cachés separadas de móvil y escritorio, el crítico por URL que el “borrar todo” no purga, y la fuente obsoleta.
- Solución duradera: inserte en línea el estado oculto + estilo completo de los componentes interactivos, después de
wp_head(), en un bloque no optimizable, con valores codificados directamente. Viaja con el tema.