{"id":8720,"date":"2025-11-04T16:59:49","date_gmt":"2025-11-04T14:59:49","guid":{"rendered":"https:\/\/seodemia.es\/blog\/?p=8720"},"modified":"2025-11-04T16:59:51","modified_gmt":"2025-11-04T14:59:51","slug":"core-web-vitals-guia-tecnica-completa-de-optimizacion-2025","status":"publish","type":"post","link":"https:\/\/seodemia.es\/blog\/core-web-vitals-guia-tecnica-completa-de-optimizacion-2025\/","title":{"rendered":"Core Web Vitals: Gu\u00eda T\u00e9cnica Completa de Optimizaci\u00f3n 2025"},"content":{"rendered":"\n<p>Los Core Web Vitals son m\u00e9tricas esenciales que Google utiliza para evaluar la experiencia de usuario en tu sitio web y que impactan directamente en tus rankings de b\u00fasqueda. Desde la actualizaci\u00f3n \u00abPage Experience\u00bb de 2021, optimizar estas m\u00e9tricas no es opcional si quieres competir en SERPs competitivos.<\/p>\n\n\n\n<p>En esta gu\u00eda t\u00e9cnica aprender\u00e1s qu\u00e9 son exactamente los Core Web Vitals, c\u00f3mo medirlos correctamente, qu\u00e9 causa los problemas m\u00e1s comunes y c\u00f3mo optimizar cada m\u00e9trica paso a paso con soluciones t\u00e9cnicas espec\u00edficas.<\/p>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>En este art\u00edculo<\/h2><nav><ul><li><a href=\"#que-son-los-core-web-vitals\">Qu\u00e9 son los Core Web Vitals<\/a><\/li><li><a href=\"#estado-actual-umbrales-y-objetivos\">Estado Actual: Umbrales y Objetivos<\/a><ul><li><a href=\"#largest-contentful-paint-lcp\">Largest Contentful Paint (LCP)<\/a><\/li><li><a href=\"#first-input-delay-fid-\u2192-interaction-to-next-paint-inp\">First Input Delay (FID) \u2192 Interaction to Next Paint (INP)<\/a><\/li><li><a href=\"#cumulative-layout-shift-cls\">Cumulative Layout Shift (CLS)<\/a><\/li><\/ul><\/li><li><a href=\"#como-medir-core-web-vitals\">C\u00f3mo Medir Core Web Vitals<\/a><ul><li><a href=\"#field-data-datos-de-campo-usuarios-reales\">Field Data (Datos de Campo &#8211; Usuarios Reales)<\/a><\/li><li><a href=\"#lab-data-datos-de-laboratorio-simulados\">Lab Data (Datos de Laboratorio &#8211; Simulados)<\/a><\/li><li><a href=\"#monitoreo-continuo-rum-real-user-monitoring\">Monitoreo Continuo (RUM &#8211; Real User Monitoring)<\/a><\/li><\/ul><\/li><li><a href=\"#optimizacion-de-lcp-largest-contentful-paint\">Optimizaci\u00f3n de LCP (Largest Contentful Paint)<\/a><ul><li><a href=\"#identificar-tu-elemento-lcp\">Identificar Tu Elemento LCP<\/a><\/li><li><a href=\"#estrategias-de-optimizacion-lcp\">Estrategias de Optimizaci\u00f3n LCP<\/a><ul><li><a href=\"#1-optimizar-servidor-y-hosting\">1. Optimizar Servidor y Hosting<\/a><\/li><li><a href=\"#2-optimizar-imagenes-lcp\">2. Optimizar Im\u00e1genes LCP<\/a><\/li><li><a href=\"#3-optimizar-web-fonts\">3. Optimizar Web Fonts<\/a><\/li><li><a href=\"#4-eliminar-recursos-que-bloquean-render\">4. Eliminar Recursos que Bloquean Render<\/a><\/li><li><a href=\"#5-reduce-tamano-de-recursos\">5. Reduce Tama\u00f1o de Recursos<\/a><\/li><li><a href=\"#6-optimiza-third-party-scripts\">6. Optimiza Third-Party Scripts<\/a><\/li><\/ul><\/li><li><a href=\"#checklist-de-optimizacion-lcp\">Checklist de Optimizaci\u00f3n LCP<\/a><\/li><\/ul><\/li><li><a href=\"#optimizacion-de-inp-interaction-to-next-paint\">Optimizaci\u00f3n de INP (Interaction to Next Paint)<\/a><ul><li><a href=\"#que-causa-inp-alto\">Qu\u00e9 Causa INP Alto<\/a><\/li><li><a href=\"#identificar-problemas-de-inp\">Identificar Problemas de INP<\/a><\/li><li><a href=\"#estrategias-de-optimizacion-inp\">Estrategias de Optimizaci\u00f3n INP<\/a><ul><li><a href=\"#1-reduce-y-optimiza-java-script\">1. Reduce y Optimiza JavaScript<\/a><\/li><li><a href=\"#2-optimiza-event-handlers\">2. Optimiza Event Handlers<\/a><\/li><li><a href=\"#3-evita-layout-thrashing\">3. Evita Layout Thrashing<\/a><\/li><li><a href=\"#4-reduce-impacto-de-third-party-scripts\">4. Reduce Impacto de Third-Party Scripts<\/a><\/li><li><a href=\"#5-optimiza-rendering\">5. Optimiza Rendering<\/a><\/li><\/ul><\/li><li><a href=\"#checklist-de-optimizacion-inp\">Checklist de Optimizaci\u00f3n INP<\/a><\/li><\/ul><\/li><li><a href=\"#optimizacion-de-cls-cumulative-layout-shift\">Optimizaci\u00f3n de CLS (Cumulative Layout Shift)<\/a><ul><li><a href=\"#causas-comunes-de-cls\">Causas Comunes de CLS<\/a><\/li><li><a href=\"#identificar-causas-de-cls\">Identificar Causas de CLS<\/a><\/li><li><a href=\"#estrategias-de-optimizacion-cls\">Estrategias de Optimizaci\u00f3n CLS<\/a><ul><li><a href=\"#1-especifica-dimensiones-de-imagenes-y-videos\">1. Especifica Dimensiones de Im\u00e1genes y Videos<\/a><\/li><li><a href=\"#2-reserva-espacio-para-ads-e-iframes\">2. Reserva Espacio para Ads e Iframes<\/a><\/li><li><a href=\"#3-optimiza-web-fonts\">3. Optimiza Web Fonts<\/a><\/li><li><a href=\"#4-evita-insertar-contenido-arriba-de-contenido-existente\">4. Evita Insertar Contenido Arriba de Contenido Existente<\/a><\/li><li><a href=\"#5-animaciones-no-deben-cambiar-layout\">5. Animaciones No Deben Cambiar Layout<\/a><\/li><li><a href=\"#6-manejo-de-contenido-above-the-fold\">6. Manejo de Contenido Above-the-Fold<\/a><\/li><\/ul><\/li><li><a href=\"#checklist-de-optimizacion-cls\">Checklist de Optimizaci\u00f3n CLS<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"que-son-los-core-web-vitals\">Qu\u00e9 son los Core Web Vitals<\/h2>\n\n\n\n<p>Core Web Vitals son un subconjunto de Web Vitals, iniciativa de Google para proporcionar m\u00e9tricas unificadas de calidad de experiencia de usuario esenciales para todos los sitios web.<\/p>\n\n\n\n<p><strong>Las tres m\u00e9tricas Core Web Vitals actuales:<\/strong><\/p>\n\n\n\n<p><strong>LCP (Largest Contentful Paint):<\/strong> mide velocidad de carga percibida. Espec\u00edficamente, cu\u00e1nto tarda en renderizar el elemento de contenido m\u00e1s grande visible en el viewport.<\/p>\n\n\n\n<p><strong>FID (First Input Delay) \/ INP (Interaction to Next Paint):<\/strong> mide interactividad. FID med\u00eda el delay de la primera interacci\u00f3n. INP (que lo reemplaz\u00f3 en marzo 2024) mide la capacidad de respuesta general durante toda la vida de la p\u00e1gina.<\/p>\n\n\n\n<p><strong>CLS (Cumulative Layout Shift):<\/strong> mide estabilidad visual. Cu\u00e1nto se mueven inesperadamente los elementos mientras la p\u00e1gina carga.<\/p>\n\n\n\n<p><strong>Por qu\u00e9 importan:<\/strong><\/p>\n\n\n\n<p>Son factores de ranking oficiales confirmados por Google. Impactan directamente la experiencia de usuario (UX). Sitios con buenos Core Web Vitals tienen menores tasas de rebote, mayor engagement y mejores conversiones. En mercados competitivos, pueden ser el diferenciador entre rankear #3 o #8.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"estado-actual-umbrales-y-objetivos\">Estado Actual: Umbrales y Objetivos<\/h2>\n\n\n\n<p>Google define umbrales espec\u00edficos para cada m\u00e9trica.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"largest-contentful-paint-lcp\">Largest Contentful Paint (LCP)<\/h3>\n\n\n\n<p><strong>Objetivo:<\/strong> \u2264 2.5 segundos <strong>Necesita mejora:<\/strong> 2.5s &#8211; 4.0s <strong>Pobre:<\/strong> &gt; 4.0 segundos<\/p>\n\n\n\n<p><strong>Qu\u00e9 mide:<\/strong> tiempo hasta que el elemento de contenido m\u00e1s grande (imagen, video, bloque de texto) se renderiza completamente en el viewport.<\/p>\n\n\n\n<p><strong>Por qu\u00e9 importa:<\/strong> usuarios perciben sitio como \u00abcargado\u00bb cuando ven el contenido principal, no cuando todos los recursos terminan de cargar.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"first-input-delay-fid-\u2192-interaction-to-next-paint-inp\">First Input Delay (FID) \u2192 Interaction to Next Paint (INP)<\/h3>\n\n\n\n<p><strong>INP (nueva m\u00e9trica desde marzo 2024):<\/strong><\/p>\n\n\n\n<p><strong>Objetivo:<\/strong> \u2264 200 milisegundos <strong>Necesita mejora:<\/strong> 200ms &#8211; 500ms <strong>Pobre:<\/strong> &gt; 500 milisegundos<\/p>\n\n\n\n<p><strong>Qu\u00e9 mide:<\/strong> latencia de todas las interacciones durante la vida de la p\u00e1gina. Mide el tiempo desde que usuario interact\u00faa (click, tap, key press) hasta que el navegador puede mostrar el siguiente frame con feedback visual.<\/p>\n\n\n\n<p><strong>Diferencia con FID:<\/strong> FID solo med\u00eda la primera interacci\u00f3n. INP eval\u00faa todas las interacciones, proporcionando m\u00e9trica m\u00e1s completa de responsividad.<\/p>\n\n\n\n<p><strong>Por qu\u00e9 importa:<\/strong> sitios que no responden inmediatamente frustran usuarios. Clicks que no hacen nada aparentemente causan abandono.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"cumulative-layout-shift-cls\">Cumulative Layout Shift (CLS)<\/h3>\n\n\n\n<p><strong>Objetivo:<\/strong> \u2264 0.1 <strong>Necesita mejora:<\/strong> 0.1 &#8211; 0.25 <strong>Pobre:<\/strong> &gt; 0.25<\/p>\n\n\n\n<p><strong>Qu\u00e9 mide:<\/strong> suma de todos los cambios de layout inesperados durante la vida de la p\u00e1gina. No tiene unidad de tiempo, es puntuaci\u00f3n.<\/p>\n\n\n\n<p><strong>C\u00e1lculo:<\/strong> Impact Fraction \u00d7 Distance Fraction para cada shift.<\/p>\n\n\n\n<p><strong>Por qu\u00e9 importa:<\/strong> intentas hacer click en bot\u00f3n y de repente se mueve porque carg\u00f3 un banner arriba. Experiencia horrible, especialmente en m\u00f3vil.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"como-medir-core-web-vitals\">C\u00f3mo Medir Core Web Vitals<\/h2>\n\n\n\n<p>Diferentes herramientas proporcionan diferentes tipos de datos.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"field-data-datos-de-campo-usuarios-reales\">Field Data (Datos de Campo &#8211; Usuarios Reales)<\/h3>\n\n\n\n<p>Datos de usuarios reales visitando tu sitio en condiciones reales (diferentes dispositivos, conexiones, ubicaciones).<\/p>\n\n\n\n<p><strong>Google Search Console:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Search Console \u2192 Experience \u2192 Core Web Vitals<\/li>\n\n\n\n<li>Muestra URLs agrupadas por estado (Good, Needs Improvement, Poor)<\/li>\n\n\n\n<li>Separado por Mobile y Desktop<\/li>\n\n\n\n<li>Datos agregados de \u00faltimos 28 d\u00edas<\/li>\n<\/ol>\n\n\n\n<p><strong>Ventaja:<\/strong> datos reales de TU audiencia espec\u00edfica.<\/p>\n\n\n\n<p><strong>Limitaci\u00f3n:<\/strong> requiere volumen m\u00ednimo de tr\u00e1fico. Sitios peque\u00f1os pueden no tener suficientes datos.<\/p>\n\n\n\n<p><strong>Chrome User Experience Report (CrUX):<\/strong><\/p>\n\n\n\n<p>Dataset p\u00fablico de datos de usuarios reales de Chrome.<\/p>\n\n\n\n<p><strong>Acceso:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CrUX Dashboard: https:\/\/lookerstudio.google.com\/datasources\/create (busca Chrome UX Report)<\/li>\n\n\n\n<li>PageSpeed Insights muestra datos CrUX si disponibles<\/li>\n\n\n\n<li>BigQuery para an\u00e1lisis avanzado<\/li>\n<\/ul>\n\n\n\n<p><strong>Ventaja:<\/strong> benchmark contra otros sitios, datos hist\u00f3ricos.<\/p>\n\n\n\n<p><strong>Web Vitals Extension (Chrome):<\/strong><\/p>\n\n\n\n<p>Extensi\u00f3n que muestra Core Web Vitals de cualquier p\u00e1gina mientras navegas.<\/p>\n\n\n\n<p><strong>Instalaci\u00f3n:<\/strong> Chrome Web Store \u2192 \u00abWeb Vitals\u00bb<\/p>\n\n\n\n<p><strong>Uso:<\/strong> \u00edcono en toolbar muestra m\u00e9tricas en tiempo real mientras visitas p\u00e1ginas.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"lab-data-datos-de-laboratorio-simulados\">Lab Data (Datos de Laboratorio &#8211; Simulados)<\/h3>\n\n\n\n<p>Datos de pruebas controladas en condiciones espec\u00edficas. \u00datil para debugging pero no refleja experiencia real de usuarios.<\/p>\n\n\n\n<p><strong>Google PageSpeed Insights:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>https:\/\/pagespeed.web.dev<\/li>\n\n\n\n<li>Introduce URL<\/li>\n\n\n\n<li>Analiza Mobile y Desktop<\/li>\n\n\n\n<li>Muestra Field Data (si disponible) y Lab Data (siempre)<\/li>\n<\/ol>\n\n\n\n<p><strong>Ventaja:<\/strong> diagn\u00f3stico detallado con recomendaciones espec\u00edficas. An\u00e1lisis inmediato sin esperar acumulaci\u00f3n de datos.<\/p>\n\n\n\n<p><strong>Limitaci\u00f3n:<\/strong> condiciones simuladas pueden no reflejar tu audiencia real.<\/p>\n\n\n\n<p><strong>Lighthouse (Integrado en Chrome DevTools):<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Chrome \u2192 F12 \u2192 Lighthouse tab<\/li>\n\n\n\n<li>Selecciona categor\u00edas (Performance m\u00ednimo)<\/li>\n\n\n\n<li>Analiza Desktop o Mobile<\/li>\n\n\n\n<li>Generate report<\/li>\n<\/ol>\n\n\n\n<p><strong>Ventaja:<\/strong> puedes probar localmente durante desarrollo, antes de publicar cambios. M\u00e1s control sobre condiciones de prueba.<\/p>\n\n\n\n<p><strong>WebPageTest:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/www.webpagetest.org\n<\/div><\/figure>\n\n\n\n<p><strong>Opciones avanzadas:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Selecciona ubicaci\u00f3n geogr\u00e1fica espec\u00edfica<\/li>\n\n\n\n<li>Tipo de conexi\u00f3n (3G, 4G, Cable)<\/li>\n\n\n\n<li>Dispositivo espec\u00edfico<\/li>\n\n\n\n<li>M\u00faltiples runs para promedios<\/li>\n\n\n\n<li>Video filmstrip de carga<\/li>\n<\/ul>\n\n\n\n<p><strong>Ventaja:<\/strong> testing m\u00e1s realista con throttling de red, m\u00faltiples ubicaciones.<\/p>\n\n\n\n<p><strong>GTmetrix:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/gtmetrix.com\n<\/div><\/figure>\n\n\n\n<p>Similar a PageSpeed pero con interfaz m\u00e1s visual, hist\u00f3rico de pruebas, alertas cuando performance empeora.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"monitoreo-continuo-rum-real-user-monitoring\">Monitoreo Continuo (RUM &#8211; Real User Monitoring)<\/h3>\n\n\n\n<p>Herramientas que recopilan datos de usuarios reales continuamente.<\/p>\n\n\n\n<p><strong>web-vitals.js (Biblioteca de Google):<\/strong><\/p>\n\n\n\n<p>JavaScript library que mide Core Web Vitals en tu sitio y los env\u00eda a tu analytics.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import {onCLS, onINP, onLCP} from 'web-vitals';\n\nonCLS(console.log);\nonINP(console.log);\nonLCP(console.log);\n<\/code><\/pre>\n\n\n\n<p>Integra con Google Analytics, custom endpoints, dataLayer.<\/p>\n\n\n\n<p><strong>Servicios de RUM comerciales:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SpeedCurve<\/li>\n\n\n\n<li>Cloudflare Web Analytics<\/li>\n\n\n\n<li>New Relic<\/li>\n\n\n\n<li>Datadog RUM<\/li>\n<\/ul>\n\n\n\n<p><strong>Ventaja:<\/strong> monitoreo 24\/7, alertas cuando m\u00e9tricas empeoran, segmentaci\u00f3n por dispositivo\/ubicaci\u00f3n\/navegador.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"optimizacion-de-lcp-largest-contentful-paint\">Optimizaci\u00f3n de LCP (Largest Contentful Paint)<\/h2>\n\n\n\n<p>LCP t\u00edpicamente es el m\u00e1s problem\u00e1tico de los tres Core Web Vitals.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"identificar-tu-elemento-lcp\">Identificar Tu Elemento LCP<\/h3>\n\n\n\n<p>Primero necesitas saber QU\u00c9 elemento es tu LCP.<\/p>\n\n\n\n<p><strong>Chrome DevTools:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>F12 \u2192 Performance tab<\/li>\n\n\n\n<li>Click \u00abRecord\u00bb y recarga p\u00e1gina<\/li>\n\n\n\n<li>Stop recording despu\u00e9s de carga completa<\/li>\n\n\n\n<li>En timeline, busca \u00abLCP\u00bb marker<\/li>\n\n\n\n<li>Click para ver qu\u00e9 elemento es<\/li>\n<\/ol>\n\n\n\n<p><strong>Elementos LCP comunes:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Hero image above the fold<\/li>\n\n\n\n<li>Video thumbnail<\/li>\n\n\n\n<li>Background image con CSS<\/li>\n\n\n\n<li>Bloque de texto grande (en p\u00e1ginas text-heavy)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"estrategias-de-optimizacion-lcp\">Estrategias de Optimizaci\u00f3n LCP<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"1-optimizar-servidor-y-hosting\">1. Optimizar Servidor y Hosting<\/h4>\n\n\n\n<p><strong>TTFB (Time to First Byte) bajo:<\/strong><\/p>\n\n\n\n<p>TTFB es fundacional para LCP. Si servidor tarda 2 segundos en responder, imposible tener LCP &lt; 2.5s.<\/p>\n\n\n\n<p><strong>Objetivo TTFB:<\/strong> &lt; 600ms (bueno), &lt; 200ms (excelente)<\/p>\n\n\n\n<p><strong>C\u00f3mo mejorar:<\/strong><\/p>\n\n\n\n<p><strong>Hosting de calidad:<\/strong> VPS o cloud hosting en lugar de shared hosting sobrecargado.<\/p>\n\n\n\n<p><strong>CDN (Content Delivery Network):<\/strong> Cloudflare, Fastly, KeyCDN sirven contenido desde servidores geogr\u00e1ficamente cercanos al usuario.<\/p>\n\n\n\n<p><strong>Server-side caching:<\/strong> p\u00e1gina HTML pre-generada en lugar de construida din\u00e1micamente en cada request.<\/p>\n\n\n\n<p><strong>Database optimization:<\/strong> queries eficientes, \u00edndices apropiados, caching de queries.<\/p>\n\n\n\n<p><strong>HTTP\/2 o HTTP\/3:<\/strong> multiplexing permite m\u00faltiples recursos en una conexi\u00f3n.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"2-optimizar-imagenes-lcp\">2. Optimizar Im\u00e1genes LCP<\/h4>\n\n\n\n<p>Si tu LCP es imagen (caso m\u00e1s com\u00fan):<\/p>\n\n\n\n<p><strong>Formato moderno:<\/strong> WebP reduce tama\u00f1o 25-35% vs JPEG. AVIF reduce 50% pero menor soporte de navegadores.<\/p>\n\n\n\n<p><strong>Compresi\u00f3n apropiada:<\/strong> usa herramientas como Squoosh, TinyPNG. JPEG quality 75-85 es sweet spot.<\/p>\n\n\n\n<p><strong>Dimensiones correctas:<\/strong> no sirvas imagen 3000x2000px si muestras 1200x800px. Resize a tama\u00f1o de display.<\/p>\n\n\n\n<p><strong>Preload de imagen LCP:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;link rel=\"preload\" as=\"image\" href=\"hero-image.webp\" fetchpriority=\"high\"&gt;\n<\/code><\/pre>\n\n\n\n<p>Esto dice al navegador: \u00abdescarga esta imagen inmediatamente, es cr\u00edtica\u00bb.<\/p>\n\n\n\n<p><strong>fetchpriority=\u00bbhigh\u00bb:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;img src=\"hero.webp\" alt=\"Hero\" fetchpriority=\"high\"&gt;\n<\/code><\/pre>\n\n\n\n<p>Navegadores modernos priorizan descarga de esta imagen sobre otras.<\/p>\n\n\n\n<p><strong>Evita lazy loading en imagen LCP:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- MAL: imagen LCP con lazy loading --&gt;\n&lt;img src=\"hero.webp\" loading=\"lazy\"&gt;\n\n&lt;!-- BIEN: carga eager (default) --&gt;\n&lt;img src=\"hero.webp\" loading=\"eager\"&gt;\n<\/code><\/pre>\n\n\n\n<p>Lazy loading retrasa carga de imagen LCP, empeorando la m\u00e9trica.<\/p>\n\n\n\n<p><strong>Responsive images con srcset:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;img \n  srcset=\"hero-400.webp 400w,\n          hero-800.webp 800w,\n          hero-1200.webp 1200w\"\n  sizes=\"(max-width: 600px) 400px,\n         (max-width: 1000px) 800px,\n         1200px\"\n  src=\"hero-800.webp\"\n  alt=\"Hero\"\n  fetchpriority=\"high\"&gt;\n<\/code><\/pre>\n\n\n\n<p>Navegador descarga tama\u00f1o apropiado seg\u00fan viewport.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"3-optimizar-web-fonts\">3. Optimizar Web Fonts<\/h4>\n\n\n\n<p>Si tu LCP es texto, web fonts pueden retrasarlo significativamente.<\/p>\n\n\n\n<p><strong>Preload de fuentes cr\u00edticas:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;link rel=\"preload\" href=\"font.woff2\" as=\"font\" type=\"font\/woff2\" crossorigin&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>font-display: swap:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@font-face {\n  font-family: 'MyFont';\n  src: url('font.woff2') format('woff2');\n  font-display: swap;\n}\n<\/code><\/pre>\n\n\n\n<p>Muestra fuente del sistema inmediatamente, cambia a custom font cuando carga. Evita FOIT (Flash of Invisible Text).<\/p>\n\n\n\n<p><strong>Limita n\u00famero de fuentes:<\/strong> cada font family y weight es archivo adicional. Usa m\u00e1ximo 2 families, 3-4 weights total.<\/p>\n\n\n\n<p><strong>Self-host fonts:<\/strong> en lugar de Google Fonts, host localmente elimina DNS lookup y latencia externa.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"4-eliminar-recursos-que-bloquean-render\">4. Eliminar Recursos que Bloquean Render<\/h4>\n\n\n\n<p><strong>CSS cr\u00edtico inline:<\/strong><\/p>\n\n\n\n<p>Extrae CSS necesario para contenido above-the-fold y ponlo inline en <code>&lt;head&gt;<\/code>. Carga resto de CSS async.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;head&gt;\n  &lt;style&gt;\n    \/* Critical CSS inline *\/\n    .hero { ... }\n    .header { ... }\n  &lt;\/style&gt;\n  \n  &lt;link rel=\"preload\" href=\"styles.css\" as=\"style\" onload=\"this.rel='stylesheet'\"&gt;\n  &lt;noscript&gt;&lt;link rel=\"stylesheet\" href=\"styles.css\"&gt;&lt;\/noscript&gt;\n&lt;\/head&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>Defer JavaScript no cr\u00edtico:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- Bloquea render --&gt;\n&lt;script src=\"script.js\"&gt;&lt;\/script&gt;\n\n&lt;!-- No bloquea render --&gt;\n&lt;script src=\"script.js\" defer&gt;&lt;\/script&gt;\n<\/code><\/pre>\n\n\n\n<p><code>defer<\/code> descarga script en paralelo sin bloquear parsing de HTML.<\/p>\n\n\n\n<p><strong>Async para scripts independientes:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script src=\"analytics.js\" async&gt;&lt;\/script&gt;\n<\/code><\/pre>\n\n\n\n<p><code>async<\/code> descarga y ejecuta inmediatamente cuando est\u00e1 listo, sin esperar a DOM complete.<\/p>\n\n\n\n<p><strong>Regla:<\/strong> usa <code>defer<\/code> para scripts que interact\u00faan con DOM, <code>async<\/code> para scripts independientes (analytics, ads).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"5-reduce-tamano-de-recursos\">5. Reduce Tama\u00f1o de Recursos<\/h4>\n\n\n\n<p><strong>Minify CSS y JavaScript:<\/strong><\/p>\n\n\n\n<p>Remove whitespace, comments, c\u00f3digo no usado.<\/p>\n\n\n\n<p>Herramientas: Terser (JS), CSSNano (CSS), webpack\/Vite\/Parcel lo hacen autom\u00e1ticamente en build.<\/p>\n\n\n\n<p><strong>Tree shaking:<\/strong> elimina c\u00f3digo JavaScript no utilizado en build.<\/p>\n\n\n\n<p><strong>Code splitting:<\/strong> divide JavaScript en chunks m\u00e1s peque\u00f1os, carga solo lo necesario.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Lazy load componente solo cuando se necesita\nimport('.\/heavy-component.js').then(module =&gt; {\n  module.init();\n});\n<\/code><\/pre>\n\n\n\n<p><strong>Compression (Gzip\/Brotli):<\/strong><\/p>\n\n\n\n<p>Comprime texto (HTML, CSS, JS) antes de enviarlo.<\/p>\n\n\n\n<p>Brotli es ~20% mejor que Gzip. Configura en servidor.<\/p>\n\n\n\n<p><strong>Apache (.htaccess):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;IfModule mod_deflate.c&gt;\n  AddOutputFilterByType DEFLATE text\/html text\/css application\/javascript\n&lt;\/IfModule&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>Nginx:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gzip on;\ngzip_types text\/css application\/javascript;\nbrotli on;\nbrotli_types text\/css application\/javascript;\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"6-optimiza-third-party-scripts\">6. Optimiza Third-Party Scripts<\/h4>\n\n\n\n<p><strong>Problema:<\/strong> scripts de terceros (analytics, ads, chat widgets) son incontrolables y frecuentemente lentos.<\/p>\n\n\n\n<p><strong>Estrategias:<\/strong><\/p>\n\n\n\n<p><strong>Defer\/async todo lo posible:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;script src=\"google-analytics.js\" async&gt;&lt;\/script&gt;\n&lt;script src=\"chatbot.js\" defer&gt;&lt;\/script&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>Lazy load widgets no cr\u00edticos:<\/strong><\/p>\n\n\n\n<p>Carga chat widget solo cuando usuario scrollea o despu\u00e9s de X segundos.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>setTimeout(() =&gt; {\n  const script = document.createElement('script');\n  script.src = 'chatbot.js';\n  document.body.appendChild(script);\n}, 5000); \/\/ Carga despu\u00e9s de 5 segundos\n<\/code><\/pre>\n\n\n\n<p><strong>Self-host cuando posible:<\/strong><\/p>\n\n\n\n<p>En lugar de cargar Google Analytics desde google.com, descarga el script y s\u00edrvelo desde tu dominio. Elimina DNS lookup externo.<\/p>\n\n\n\n<p><strong>Usa facades:<\/strong> para embeds de YouTube, Facebook, muestra thumbnail est\u00e1tica, carga iframe real solo cuando usuario hace click.<\/p>\n\n\n\n<p><strong>Audit regular:<\/strong> revisa qu\u00e9 scripts third-party realmente necesitas. Elimina lo innecesario.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"checklist-de-optimizacion-lcp\">Checklist de Optimizaci\u00f3n LCP<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2713 TTFB &lt; 600ms (preferible &lt; 200ms)<\/li>\n\n\n\n<li>\u2713 CDN implementado<\/li>\n\n\n\n<li>\u2713 Server-side caching activo<\/li>\n\n\n\n<li>\u2713 Imagen LCP optimizada (WebP, comprimida, dimensiones correctas)<\/li>\n\n\n\n<li>\u2713 Preload en imagen\/recurso LCP<\/li>\n\n\n\n<li>\u2713 fetchpriority=\u00bbhigh\u00bb en elemento LCP<\/li>\n\n\n\n<li>\u2713 NO lazy loading en elemento LCP<\/li>\n\n\n\n<li>\u2713 CSS cr\u00edtico inline, resto async<\/li>\n\n\n\n<li>\u2713 JavaScript defer o async<\/li>\n\n\n\n<li>\u2713 Web fonts preloaded con font-display: swap<\/li>\n\n\n\n<li>\u2713 Third-party scripts diferidos<\/li>\n\n\n\n<li>\u2713 Gzip\/Brotli compression habilitado<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"optimizacion-de-inp-interaction-to-next-paint\">Optimizaci\u00f3n de INP (Interaction to Next Paint)<\/h2>\n\n\n\n<p>INP mide responsividad durante toda la sesi\u00f3n, no solo primera interacci\u00f3n.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"que-causa-inp-alto\">Qu\u00e9 Causa INP Alto<\/h3>\n\n\n\n<p><strong>Long tasks (tareas largas):<\/strong> JavaScript que bloquea el main thread &gt; 50ms.<\/p>\n\n\n\n<p><strong>Event handlers pesados:<\/strong> c\u00f3digo que se ejecuta en respuesta a clicks\/taps tarda demasiado.<\/p>\n\n\n\n<p><strong>Layout thrashing:<\/strong> cambios de DOM que fuerzan recalculations repetidos de layout.<\/p>\n\n\n\n<p><strong>Third-party scripts:<\/strong> especialmente ads y analytics mal optimizados.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"identificar-problemas-de-inp\">Identificar Problemas de INP<\/h3>\n\n\n\n<p><strong>Chrome DevTools &#8211; Performance:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>F12 \u2192 Performance<\/li>\n\n\n\n<li>Record mientras interact\u00faas con la p\u00e1gina (clicks, scrolls, typing)<\/li>\n\n\n\n<li>Stop recording<\/li>\n\n\n\n<li>Busca \u00abLong Tasks\u00bb (marcados en rojo si > 50ms)<\/li>\n\n\n\n<li>Identifica qu\u00e9 c\u00f3digo causa long tasks<\/li>\n<\/ol>\n\n\n\n<p><strong>web-vitals.js con attribution:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import {onINP} from 'web-vitals\/attribution';\n\nonINP(({name, value, attribution}) =&gt; {\n  console.log('INP:', value);\n  console.log('Element:', attribution.interactionTarget);\n  console.log('Event type:', attribution.interactionType);\n});\n<\/code><\/pre>\n\n\n\n<p>Te dice exactamente qu\u00e9 interacci\u00f3n y elemento causan INP alto.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"estrategias-de-optimizacion-inp\">Estrategias de Optimizaci\u00f3n INP<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"1-reduce-y-optimiza-java-script\">1. Reduce y Optimiza JavaScript<\/h4>\n\n\n\n<p><strong>Code splitting:<\/strong><\/p>\n\n\n\n<p>Divide JavaScript en chunks m\u00e1s peque\u00f1os. Carga solo c\u00f3digo necesario para ruta actual.<\/p>\n\n\n\n<p><strong>Ejemplo con webpack:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Lazy load modal component\nbutton.addEventListener('click', async () =&gt; {\n  const {Modal} = await import('.\/modal.js');\n  new Modal().show();\n});\n<\/code><\/pre>\n\n\n\n<p><strong>Debounce\/throttle en event handlers:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ MAL: ejecuta en cada keypress\ninput.addEventListener('input', () =&gt; {\n  expensiveFunction();\n});\n\n\/\/ BIEN: ejecuta m\u00e1ximo cada 300ms\ninput.addEventListener('input', debounce(() =&gt; {\n  expensiveFunction();\n}, 300));\n\nfunction debounce(func, wait) {\n  let timeout;\n  return function executedFunction(...args) {\n    clearTimeout(timeout);\n    timeout = setTimeout(() =&gt; func(...args), wait);\n  };\n}\n<\/code><\/pre>\n\n\n\n<p><strong>Web Workers para tareas pesadas:<\/strong><\/p>\n\n\n\n<p>Mueve computaci\u00f3n intensiva fuera del main thread.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ main.js\nconst worker = new Worker('worker.js');\nworker.postMessage({data: largeDataset});\nworker.onmessage = (e) =&gt; {\n  console.log('Resultado:', e.data);\n};\n\n\/\/ worker.js\nself.onmessage = (e) =&gt; {\n  const result = heavyComputation(e.data);\n  self.postMessage(result);\n};\n<\/code><\/pre>\n\n\n\n<p><strong>requestIdleCallback para tareas no urgentes:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>requestIdleCallback(() =&gt; {\n  \/\/ C\u00f3digo que puede esperar hasta que navegador est\u00e9 idle\n  analytics.sendData();\n  preloadNextPage();\n});\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"2-optimiza-event-handlers\">2. Optimiza Event Handlers<\/h4>\n\n\n\n<p><strong>Event delegation:<\/strong><\/p>\n\n\n\n<p>En lugar de 100 listeners individuales, uno solo en contenedor padre.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ MAL: listener en cada bot\u00f3n\nbuttons.forEach(btn =&gt; {\n  btn.addEventListener('click', handleClick);\n});\n\n\/\/ BIEN: un listener en container\ncontainer.addEventListener('click', (e) =&gt; {\n  if (e.target.matches('button')) {\n    handleClick(e);\n  }\n});\n<\/code><\/pre>\n\n\n\n<p><strong>Passive event listeners:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Dice al navegador que no llamar\u00e1s preventDefault()\nelement.addEventListener('touchstart', handler, {passive: true});\n<\/code><\/pre>\n\n\n\n<p>Permite al navegador scrollear inmediatamente sin esperar a que handler termine.<\/p>\n\n\n\n<p><strong>Prioriza feedback visual inmediato:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>button.addEventListener('click', () =&gt; {\n  \/\/ Feedback visual inmediato\n  button.classList.add('loading');\n  \n  \/\/ L\u00f3gica pesada despu\u00e9s\n  setTimeout(() =&gt; {\n    expensiveOperation();\n  }, 0);\n});\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"3-evita-layout-thrashing\">3. Evita Layout Thrashing<\/h4>\n\n\n\n<p><strong>Batch DOM reads y writes:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ MAL: causa m\u00faltiples recalculations\nelements.forEach(el =&gt; {\n  const height = el.offsetHeight; \/\/ Read\n  el.style.height = height + 10 + 'px'; \/\/ Write\n  \/\/ Repeat causes forced reflow cada vez\n});\n\n\/\/ BIEN: agrupa reads, luego writes\nconst heights = elements.map(el =&gt; el.offsetHeight); \/\/ All reads\nelements.forEach((el, i) =&gt; {\n  el.style.height = heights&#91;i] + 10 + 'px'; \/\/ All writes\n});\n<\/code><\/pre>\n\n\n\n<p><strong>Usa CSS transforms en lugar de position\/dimensions:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* MAL: causa reflow *\/\n.animated {\n  position: relative;\n  left: 100px;\n}\n\n\/* BIEN: solo compositor *\/\n.animated {\n  transform: translateX(100px);\n}\n<\/code><\/pre>\n\n\n\n<p>Transforms y opacity solo afectan compositor layer, no causan reflow\/repaint.<\/p>\n\n\n\n<p><strong>requestAnimationFrame para cambios visuales:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Sincroniza con refresh rate del navegador\nfunction animate() {\n  element.style.transform = `translateX(${x}px)`;\n  requestAnimationFrame(animate);\n}\nrequestAnimationFrame(animate);\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"4-reduce-impacto-de-third-party-scripts\">4. Reduce Impacto de Third-Party Scripts<\/h4>\n\n\n\n<p><strong>Carga diferida:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Carga chat widget solo despu\u00e9s de interacci\u00f3n\nlet chatLoaded = false;\ndocument.addEventListener('scroll', () =&gt; {\n  if (!chatLoaded) {\n    loadChatWidget();\n    chatLoaded = true;\n  }\n}, {once: true, passive: true});\n<\/code><\/pre>\n\n\n\n<p><strong>Sandbox en iframes:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;iframe \n  src=\"third-party.html\" \n  sandbox=\"allow-scripts\"\n  loading=\"lazy\"&gt;\n&lt;\/iframe&gt;\n<\/code><\/pre>\n\n\n\n<p>Limita lo que c\u00f3digo third-party puede hacer.<\/p>\n\n\n\n<p><strong>Monitoring y accountability:<\/strong><\/p>\n\n\n\n<p>Usa Resource Timing API para medir cu\u00e1nto tarda cada script third-party:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>performance.getEntriesByType('resource')\n  .filter(r =&gt; r.name.includes('analytics'))\n  .forEach(r =&gt; console.log(r.name, r.duration));\n<\/code><\/pre>\n\n\n\n<p>Si script espec\u00edfico causa problemas, considera alternativa o eliminarlo.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"5-optimiza-rendering\">5. Optimiza Rendering<\/h4>\n\n\n\n<p><strong>CSS containment:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.card {\n  contain: layout style paint;\n}\n<\/code><\/pre>\n\n\n\n<p>Dice al navegador que cambios dentro de .card no afectan fuera. Optimiza reflows.<\/p>\n\n\n\n<p><strong>content-visibility:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.long-article section {\n  content-visibility: auto;\n}\n<\/code><\/pre>\n\n\n\n<p>Renderiza solo secciones visibles en viewport. Dram\u00e1tico improvement en p\u00e1ginas largas.<\/p>\n\n\n\n<p><strong>will-change (con cuidado):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.animated-element {\n  will-change: transform;\n}\n<\/code><\/pre>\n\n\n\n<p>Optimiza elemento para animaci\u00f3n. No abuses (crea layers adicionales, consume memoria).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"checklist-de-optimizacion-inp\">Checklist de Optimizaci\u00f3n INP<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2713 Total JavaScript bundle &lt; 300KB (mobile)<\/li>\n\n\n\n<li>\u2713 No long tasks > 50ms durante interacciones cr\u00edticas<\/li>\n\n\n\n<li>\u2713 Event handlers optimizados (delegation, debounce)<\/li>\n\n\n\n<li>\u2713 Third-party scripts diferidos o lazy loaded<\/li>\n\n\n\n<li>\u2713 Web Workers para tareas computacionales pesadas<\/li>\n\n\n\n<li>\u2713 DOM manipulation batched (no thrashing)<\/li>\n\n\n\n<li>\u2713 Transforms\/opacity para animaciones (no layout properties)<\/li>\n\n\n\n<li>\u2713 Passive event listeners donde apropiado<\/li>\n\n\n\n<li>\u2713 Code splitting implementado<\/li>\n\n\n\n<li>\u2713 Feedback visual inmediato en interacciones<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"optimizacion-de-cls-cumulative-layout-shift\">Optimizaci\u00f3n de CLS (Cumulative Layout Shift)<\/h2>\n\n\n\n<p>CLS mide estabilidad visual. Elementos que \u00absaltan\u00bb mientras p\u00e1gina carga.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"causas-comunes-de-cls\">Causas Comunes de CLS<\/h3>\n\n\n\n<p><strong>Im\u00e1genes sin dimensiones:<\/strong> navegador no sabe cu\u00e1nto espacio reservar, causa shift cuando carga.<\/p>\n\n\n\n<p><strong>Ads, embeds, iframes sin dimensiones:<\/strong> mismo problema.<\/p>\n\n\n\n<p><strong>Fonts que cargan tarde:<\/strong> FOIT o FOUT causa texto que salta.<\/p>\n\n\n\n<p><strong>Contenido inyectado din\u00e1micamente:<\/strong> banners, notificaciones que pushean contenido existente.<\/p>\n\n\n\n<p><strong>Animaciones mal implementadas:<\/strong> cambios de height\/width en lugar de transform.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"identificar-causas-de-cls\">Identificar Causas de CLS<\/h3>\n\n\n\n<p><strong>Chrome DevTools:<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>F12 \u2192 Performance<\/li>\n\n\n\n<li>Experience section \u2192 Layout Shifts<\/li>\n\n\n\n<li>Click en cada shift para ver qu\u00e9 elemento lo caus\u00f3<\/li>\n<\/ol>\n\n\n\n<p><strong>web-vitals.js con attribution:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import {onCLS} from 'web-vitals\/attribution';\n\nonCLS(({value, attribution}) =&gt; {\n  console.log('CLS:', value);\n  attribution.largestShiftSource &amp;&amp; console.log('Element:', attribution.largestShiftSource);\n});\n<\/code><\/pre>\n\n\n\n<p><strong>Layout Shift GIF Debugger (Chrome Extension):<\/strong><\/p>\n\n\n\n<p>Genera GIF animado mostrando exactamente qu\u00e9 elementos se mueven y cu\u00e1ndo.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"estrategias-de-optimizacion-cls\">Estrategias de Optimizaci\u00f3n CLS<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"1-especifica-dimensiones-de-imagenes-y-videos\">1. Especifica Dimensiones de Im\u00e1genes y Videos<\/h4>\n\n\n\n<p><strong>Siempre include width y height:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- MAL: sin dimensiones --&gt;\n&lt;img src=\"photo.jpg\" alt=\"Photo\"&gt;\n\n&lt;!-- BIEN: con dimensiones --&gt;\n&lt;img src=\"photo.jpg\" alt=\"Photo\" width=\"800\" height=\"600\"&gt;\n<\/code><\/pre>\n\n\n\n<p>Navegador reserva espacio correcto bas\u00e1ndose en aspect ratio incluso antes de cargar imagen.<\/p>\n\n\n\n<p><strong>Para responsive images, usa aspect-ratio CSS:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>img {\n  max-width: 100%;\n  height: auto;\n  aspect-ratio: 16 \/ 9;\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;img src=\"photo.jpg\" alt=\"Photo\" style=\"aspect-ratio: 16\/9\"&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>Videos:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;video width=\"1920\" height=\"1080\" poster=\"thumbnail.jpg\"&gt;\n  &lt;source src=\"video.mp4\" type=\"video\/mp4\"&gt;\n&lt;\/video&gt;\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"2-reserva-espacio-para-ads-e-iframes\">2. Reserva Espacio para Ads e Iframes<\/h4>\n\n\n\n<p><strong>Contenedor con min-height:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.ad-slot {\n  min-height: 250px; \/* Altura t\u00edpica de tu ad *\/\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div class=\"ad-slot\"&gt;\n  &lt;!-- Ad code aqu\u00ed --&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>Placeholder con aspect ratio:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.embed-container {\n  position: relative;\n  padding-bottom: 56.25%; \/* 16:9 aspect ratio *\/\n  height: 0;\n  overflow: hidden;\n}\n\n.embed-container iframe {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div class=\"embed-container\"&gt;\n  &lt;iframe src=\"youtube-video\"&gt;&lt;\/iframe&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"3-optimiza-web-fonts\">3. Optimiza Web Fonts<\/h4>\n\n\n\n<p><strong>font-display: swap o optional:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@font-face {\n  font-family: 'CustomFont';\n  src: url('font.woff2') format('woff2');\n  font-display: swap; \/* Muestra fallback, luego cambia *\/\n  \/* O *\/\n  font-display: optional; \/* Usa custom si carga r\u00e1pido, sino fallback *\/\n}\n<\/code><\/pre>\n\n\n\n<p><strong>Preload fonts cr\u00edticos:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;link rel=\"preload\" href=\"font.woff2\" as=\"font\" type=\"font\/woff2\" crossorigin&gt;\n<\/code><\/pre>\n\n\n\n<p><strong>Subset fonts:<\/strong> incluye solo caracteres que usas. Reduce tama\u00f1o = carga m\u00e1s r\u00e1pida.<\/p>\n\n\n\n<p><strong>Usa variable fonts:<\/strong> un archivo con m\u00faltiples weights en lugar de archivo por weight.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"4-evita-insertar-contenido-arriba-de-contenido-existente\">4. Evita Insertar Contenido Arriba de Contenido Existente<\/h4>\n\n\n\n<p><strong>Banners\/notificaciones:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* MAL: pushea contenido *\/\n.banner {\n  position: relative;\n}\n\n\/* BIEN: overlay sin pushear *\/\n.banner {\n  position: fixed;\n  top: 0;\n  width: 100%;\n  z-index: 1000;\n}\n<\/code><\/pre>\n\n\n\n<p>O usa <code>position: sticky<\/code> si quieres que scrolle con p\u00e1gina pero no pushee contenido inicial.<\/p>\n\n\n\n<p><strong>Contenido din\u00e1mico:<\/strong><\/p>\n\n\n\n<p>Si cargas contenido v\u00eda AJAX y lo insertas, hazlo al final o en contenedor con altura definida.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ MAL: inserta al principio, pushea todo\ncontainer.prepend(newContent);\n\n\/\/ BIEN: inserta al final\ncontainer.append(newContent);\n\n\/\/ O: contenedor con altura fija que no cambia\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"5-animaciones-no-deben-cambiar-layout\">5. Animaciones No Deben Cambiar Layout<\/h4>\n\n\n\n<p><strong>Usa transforms, no top\/left\/width\/height:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* MAL: causa layout shift *\/\n.slide-in {\n  animation: slideIn 0.3s;\n}\n@keyframes slideIn {\n  from { left: -100px; }\n  to { left: 0; }\n}\n\n\/* BIEN: solo compositor *\/\n.slide-in {\n  animation: slideIn 0.3s;\n}\n@keyframes slideIn {\n  from { transform: translateX(-100px); }\n  to { transform: translateX(0); }\n}\n<\/code><\/pre>\n\n\n\n<p><strong>Properties que NO causan layout:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>transform<\/code><\/li>\n\n\n\n<li><code>opacity<\/code><\/li>\n<\/ul>\n\n\n\n<p><strong>Properties que S\u00cd causan layout:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>width<\/code>, <code>height<\/code><\/li>\n\n\n\n<li><code>margin<\/code>, <code>padding<\/code><\/li>\n\n\n\n<li><code>top<\/code>, <code>left<\/code>, <code>right<\/code>, <code>bottom<\/code><\/li>\n\n\n\n<li><code>font-size<\/code><\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"6-manejo-de-contenido-above-the-fold\">6. Manejo de Contenido Above-the-Fold<\/h4>\n\n\n\n<p><strong>Skeleton screens:<\/strong><\/p>\n\n\n\n<p>En lugar de espacio vac\u00edo que salta cuando carga contenido, muestra placeholder con forma similar.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;div class=\"skeleton\"&gt;\n  &lt;div class=\"skeleton-header\"&gt;&lt;\/div&gt;\n  &lt;div class=\"skeleton-text\"&gt;&lt;\/div&gt;\n  &lt;div class=\"skeleton-text\"&gt;&lt;\/div&gt;\n&lt;\/div&gt;\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>.skeleton {\n  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);\n  background-size: 200% 100%;\n  animation: loading 1.5s infinite;\n}\n@keyframes loading {\n  0% { background-position: 200% 0; }\n  100% { background-position: -200% 0; }\n}\n<\/code><\/pre>\n\n\n\n<p>Usuario ve que algo est\u00e1 cargando, espacio est\u00e1 reservado.<\/p>\n\n\n\n<p><strong>Progressive rendering:<\/strong><\/p>\n\n\n\n<p>Muestra estructura b\u00e1sica inmediatamente, enhancement despu\u00e9s.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- Carga inmediata: estructura b\u00e1sica --&gt;\n&lt;article&gt;\n  &lt;h1&gt;Title&lt;\/h1&gt;\n  &lt;div id=\"content-placeholder\" style=\"min-height: 500px\"&gt;\n    Loading...\n  &lt;\/div&gt;\n&lt;\/article&gt;\n\n&lt;script&gt;\n\/\/ Contenido rich despu\u00e9s\nfetch('\/api\/content').then(html =&gt; {\n  document.getElementById('content-placeholder').innerHTML = html;\n});\n&lt;\/script&gt;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"checklist-de-optimizacion-cls\">Checklist de Optimizaci\u00f3n CLS<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2713 Todas las im\u00e1genes tienen width\/height o aspect-ratio<\/li>\n\n\n\n<li>\u2713 Videos especifican dimensiones<\/li>\n\n\n\n<li>\u2713 Ads e iframes tienen espacio reservado (min-height)<\/li>\n\n\n\n<li>\u2713 Web fonts con font-display: swap\/optional<\/li>\n\n\n\n<li>\u2713 Fonts cr\u00edticos preloaded<\/li>\n\n\n\n<li>\u2713 No hay conteni<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Los Core Web Vitals son m\u00e9tricas esenciales que Google utiliza para evaluar la experiencia de usuario en tu sitio web y que impactan directamente en tus rankings de b\u00fasqueda. Desde la actualizaci\u00f3n \u00abPage Experience\u00bb de 2021, optimizar estas m\u00e9tricas no es opcional si quieres competir en SERPs competitivos. En esta gu\u00eda t\u00e9cnica aprender\u00e1s qu\u00e9 son [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":8723,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31,24],"tags":[52,59,166,169],"class_list":["post-8720","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guias","category-google","tag-auditoria-seo","tag-core-web-vitals","tag-seo-2025","tag-seo-tecnico"],"_links":{"self":[{"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/posts\/8720","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/comments?post=8720"}],"version-history":[{"count":1,"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/posts\/8720\/revisions"}],"predecessor-version":[{"id":8724,"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/posts\/8720\/revisions\/8724"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/media\/8723"}],"wp:attachment":[{"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/media?parent=8720"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/categories?post=8720"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/seodemia.es\/blog\/wp-json\/wp\/v2\/tags?post=8720"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}