El error que en realidad era el depurador
Mientras revisaba el layout móvil de una página nueva, encontré lo que parecía un error real y feo: en un viewport angosto de ancho de teléfono, el texto se recortaba en el borde derecho por todos lados, la navegación, el encabezado del hero, el texto del cuerpo, las etiquetas de los botones. Cada sección, cortada a mitad de palabra. Lo registré, seguí adelante, y volví después para arreglarlo bien. Tomó unos veinte minutos de instrumentar la página real para descubrir que el error no estaba en el sitio en absoluto. Estaba en la herramienta que usaba para mirar el sitio.
La configuración que parecía condenatoria. Pruebo los layouts móviles con la CLI de Chrome headless, sin Playwright, sin cliente CDP, solo --headless=new --window-size=390,1200 --screenshot=out.png, ya que es lo que hay disponible en este entorno. Funcionó bien para todas las demás verificaciones visuales que este proyecto necesitó. Así que cuando una captura a 390px mostró “IMPERFECT SYSTEMS” cortado a la mitad y “Read the dev lo” sin su g, le creí. El patrón (recorte idéntico en un header fijo, un hero centrado, y una grilla de tarjetas, tres componentes que no comparten lógica de layout) debería haber sido la señal, pero “todo está roto de la misma forma” se lee como “hay una sola causa raíz” con la misma facilidad que se lee como “la herramienta de medición está rota,” y no me detuve a distinguir entre ambas antes de registrar el issue.
Lo que en realidad pasó. Volví a entrarle para arreglarlo bien, lo que significaba encontrar el elemento específico que causaba el desbordamiento antes de tocar cualquier CSS. Como no hay acceso real a devtools en esta configuración, inyecté un pequeño script directamente en una copia del HTML compilado (el mismo truco usado antes para las verificaciones de accesibilidad) para registrar window.innerWidth y marcar cualquier elemento más ancho que el viewport. Primera corrida: innerWidth=500. No 390. Había pedido 390.
Probé cada ancho de 320 a 499, en los modos headless nuevo y heredado. Todos y cada uno se limitaron a exactamente 500px. Esta versión de Chrome tiene un piso duro: pedir algo más angosto hace que renderice en silencio a 500 en su lugar. Nada avisa que esto haya pasado. La opción --screenshot no sabe ni le importa que el ancho de renderizado no coincidiera con lo pedido; de todas formas guarda el archivo con las dimensiones solicitadas, lo que significa que el PNG es un recorte de una página más ancha, no una captura fiel. Ese recorte es indistinguible, a simple vista, de contenido real desbordando el viewport, porque se ve exactamente igual.
Demostrando el negativo. Descubrir que la herramienta mentía era solo la mitad del trabajo. Todavía necesitaba saber si había un error real escondido debajo del falso. Cero elementos desbordados en cada ancho que pude renderizar de verdad (hasta ese piso de 500px) tanto en la portada como en la página que estaba probando cuando noté esto por primera vez. Un grep por cada archivo de componente y de layout en busca de los culpables usuales (anchos fijos en píxeles, texto que se niega a hacer wrap, flex-wrap faltante) arrojó exactamente un candidato, una insignia de estado que no hace wrap, y esa entra sin problema incluso a 500px. Fue lo más cercano a un certificado de salud limpio que pude conseguir sin herramientas reales de emulación de dispositivos, que este entorno no tiene.
Qué haría distinto. El instinto de confiar en una captura porque “ya usé esta herramienta antes y siempre funcionó” es exactamente cómo un punto ciego de herramientas sobrevive más allá de cuando debería haberse detectado. La solución no es “no confiar en las herramientas”, es notar cuándo la forma de un error no coincide con su supuesta causa. Un error de layout específico de un componente se parece a ese componente. Un error que golpea a tres componentes sin relación de forma idéntica se parece a la herramienta que mide a los tres, y vale la pena interrogar eso en silencio durante cinco minutos antes de escribir un issue que diga lo contrario.
Lecturas relacionadas
Mi corrección fue correcta todo el tiempo, mi servidor de desarrollo simplemente se negaba a decirlo
Vite no vigila node_modules, un servidor detenido que en realidad no lo estaba, y el respaldo de puerto que me hizo probar el código de la semana pasada mientras leía el código fuente de esta semana.
La suite de pruebas en verde que no probaba lo que yo pensaba que probaba
Un override de seguridad que pasó todas las verificaciones en local, y una llamada directa de cinco líneas que mostró que falla en tiempo de ejecución porque la forma de exportación del módulo cambió entre versiones mayores.
Un falso 34 de 36 aprobados, y la oración que decía lo mismo dos veces
Una suite de accesibilidad que escaneó en silencio un sitio completamente distinto, porque algo más ya estaba escuchando en el puerto que necesitaba.