{"id":3895,"date":"2026-10-11T11:42:43","date_gmt":"2026-10-11T09:42:43","guid":{"rendered":"https:\/\/mantenimientoweb.pro\/blog\/que-es-el-lazy-loading-carga-diferida-y-como-programarlo-sin-usar-plugins\/"},"modified":"2026-10-11T11:42:45","modified_gmt":"2026-10-11T09:42:45","slug":"que-es-el-lazy-loading-carga-diferida-y-como-programarlo-sin-usar-plugins","status":"publish","type":"post","link":"https:\/\/mantenimientoweb.pro\/blog\/que-es-el-lazy-loading-carga-diferida-y-como-programarlo-sin-usar-plugins\/","title":{"rendered":"\u00bfQu\u00e9 es el \u00abLazy Loading\u00bb (Carga Diferida) y c\u00f3mo programarlo sin usar plugins?"},"content":{"rendered":"<article>\n<p>      \u00bfQu\u00e9 es el \u201cLazy Loading\u201d o carga diferida y c\u00f3mo programarlo sin usar plugins? \ud83d\ude80<\/p>\n<p>Hay p\u00e1ginas web que entran en escena como un elefante en una cristaler\u00eda: cargan todo, absolutamente todo, aunque el visitante solo haya visto el primer pantallazo. Im\u00e1genes del pie de p\u00e1gina, v\u00eddeos enterrados en la mitad del art\u00edculo, iframes de mapas que nadie ha pedido todav\u00eda\u2026 todo desfila por la red como si el ancho de banda fuera infinito y la paciencia humana, tambi\u00e9n. El <strong>Lazy Loading<\/strong>, o <strong>carga diferida<\/strong>, nace precisamente para poner orden en ese banquete desmesurado.<\/p>\n<p>La idea es sencilla, casi humilde: <strong>no cargues lo que todav\u00eda no se necesita<\/strong>. Una imagen que est\u00e1 a cinco scrolls de distancia puede esperar. Un v\u00eddeo incrustado al final de una landing page no tiene por qu\u00e9 competir con el logotipo, el texto principal o la fotograf\u00eda hero. En un mundo obsesionado con \u201cm\u00e1s, m\u00e1s, m\u00e1s\u201d, el Lazy Loading propone una peque\u00f1a herej\u00eda: menos al principio, mejor despu\u00e9s.<\/p>\n<p>Y s\u00ed, se puede implementar sin plugins. De hecho, en muchos casos conviene hacerlo as\u00ed. Instalar un plugin para cargar menos recursos tiene cierto encanto ir\u00f3nico: a\u00f1adir m\u00e1s c\u00f3digo para reducir c\u00f3digo, como comprarse una cinta de correr para ir en coche al gimnasio. A veces se justifica; muchas otras, no.<\/p>\n<p>        <strong>\u00cdndice r\u00e1pido \ud83d\udccc<\/strong><\/p>\n<ol>\n<li><a href=\"#que-es\">Qu\u00e9 es realmente el Lazy Loading<\/a><\/li>\n<li><a href=\"#beneficios\">Por qu\u00e9 mejora el rendimiento web<\/a><\/li>\n<li><a href=\"#cuando-no-usarlo\">Cu\u00e1ndo no debes usar carga diferida<\/a><\/li>\n<li><a href=\"#html-nativo\">Implementaci\u00f3n con HTML nativo<\/a><\/li>\n<li><a href=\"#javascript\">Lazy Loading con JavaScript e Intersection Observer<\/a><\/li>\n<li><a href=\"#wordpress\">C\u00f3mo programarlo en WordPress sin plugins<\/a><\/li>\n<li><a href=\"#fondos-css\">Carga diferida para fondos CSS<\/a><\/li>\n<li><a href=\"#seo\">SEO, accesibilidad y Core Web Vitals<\/a><\/li>\n<li><a href=\"#errores\">Errores frecuentes y buenas pr\u00e1cticas<\/a><\/li>\n<li><a href=\"#pruebas\">C\u00f3mo comprobar que funciona<\/a><\/li>\n<\/ol>\n<h2 id=\"que-es\">Qu\u00e9 es realmente el Lazy Loading \ud83d\udca4<\/h2>\n<p>El <strong>Lazy Loading<\/strong> es una t\u00e9cnica de optimizaci\u00f3n web que retrasa la carga de determinados recursos \u2014normalmente im\u00e1genes, iframes, v\u00eddeos, scripts o fondos visuales\u2014 hasta que son necesarios o est\u00e1n cerca de ser visibles para el usuario.<\/p>\n<p>Dicho de otra manera: la p\u00e1gina no sirve todos sus platos de golpe. Primero trae el pan, el agua, quiz\u00e1 la sopa. El postre llegar\u00e1 cuando toque. Una web sin carga diferida, en cambio, se comporta como un camarero nervioso que apila entrada, plato fuerte, caf\u00e9 y cuenta sobre la misma mesa. Muy eficiente en apariencia. Bastante absurdo en la pr\u00e1ctica.<\/p>\n<p>En t\u00e9rminos t\u00e9cnicos, la carga diferida ayuda a reducir la cantidad de datos descargados durante la carga inicial. Esto puede mejorar m\u00e9tricas importantes como:<\/p>\n<ul>\n<li><strong>Tiempo de carga inicial<\/strong>: la p\u00e1gina empieza a estar disponible antes.<\/li>\n<li><strong>Largest Contentful Paint o LCP<\/strong>: mide cu\u00e1ndo se renderiza el elemento principal visible.<\/li>\n<li><strong>First Contentful Paint o FCP<\/strong>: indica cu\u00e1ndo aparece el primer contenido \u00fatil.<\/li>\n<li><strong>Time to Interactive o TTI<\/strong>: aunque ya no sea una m\u00e9trica central en Lighthouse, sigue siendo \u00fatil para entender cu\u00e1ndo la p\u00e1gina puede responder.<\/li>\n<li><strong>Uso de ancho de banda<\/strong>: especialmente importante en m\u00f3viles y conexiones lentas.<\/li>\n<li><strong>Consumo de memoria<\/strong>: menos recursos cargados implica menos presi\u00f3n sobre el navegador.<\/li>\n<\/ul>\n<p>La t\u00e9cnica no es nueva. Durante a\u00f1os se implement\u00f3 con JavaScript personalizado, observando el scroll como quien vigila nubes antes de una tormenta. Hoy, los navegadores modernos soportan carga diferida nativa mediante el atributo <code>loading=\"lazy\"<\/code> en im\u00e1genes e iframes. Eso simplifica mucho la vida. No la resuelve toda, claro. La web rara vez concede milagros completos.<\/p>\n<h2 id=\"beneficios\">Por qu\u00e9 mejora el rendimiento web \u26a1<\/h2>\n<p>Para entender su impacto, conviene imaginar una p\u00e1gina larga: un art\u00edculo con 30 im\u00e1genes, varios anuncios, un mapa de Google, un v\u00eddeo de YouTube y algunos widgets sociales. Sin Lazy Loading, el navegador comienza a pedir muchos recursos desde el inicio. Aunque el usuario solo vea la cabecera y los primeros p\u00e1rrafos, la p\u00e1gina ya est\u00e1 descargando elementos que viven en las profundidades del documento.<\/p>\n<p>Eso genera competencia. Las im\u00e1genes del final compiten con los recursos cr\u00edticos del principio: CSS, fuentes, imagen principal, JavaScript esencial. Es la vieja pelea entre lo urgente y lo accesorio. Y, como suele ocurrir, lo accesorio hace ruido.<\/p>\n<p>La carga diferida permite que los recursos importantes respiren. Al aplazar lo secundario, se mejora la percepci\u00f3n de velocidad y, en muchos casos, tambi\u00e9n la velocidad real.<\/p>\n<table>\n<thead>\n<tr>\n<th>Elemento<\/th>\n<th>Sin Lazy Loading<\/th>\n<th>Con Lazy Loading<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Im\u00e1genes bajo el primer pantallazo<\/td>\n<td>Se descargan desde el inicio, aunque el usuario no las vea.<\/td>\n<td>Se cargan cuando est\u00e1n cerca del viewport.<\/td>\n<\/tr>\n<tr>\n<td>Iframes de YouTube, mapas o redes sociales<\/td>\n<td>Pueden bloquear o ralentizar la carga inicial.<\/td>\n<td>Se posponen hasta que el usuario se aproxima.<\/td>\n<\/tr>\n<tr>\n<td>Datos m\u00f3viles<\/td>\n<td>Se consumen incluso si el usuario abandona r\u00e1pido.<\/td>\n<td>Se descargan solo los recursos potencialmente necesarios.<\/td>\n<\/tr>\n<tr>\n<td>Core Web Vitals<\/td>\n<td>Puede perjudicar LCP y la experiencia percibida.<\/td>\n<td>Puede mejorar el rendimiento si se aplica con criterio.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>        <strong>Dato importante:<\/strong> Lazy Loading no significa que la web pese menos en total si el usuario acaba recorri\u00e9ndola completa. Significa que <strong>no carga todo al principio<\/strong>. Es una diferencia sutil, pero decisiva.<\/p>\n<p>Recuerdo una auditor\u00eda de rendimiento \u2014peque\u00f1a digresi\u00f3n, pero viene al caso\u2014 en la que una home corporativa cargaba m\u00e1s de 18 MB en la primera visita. La empresa vend\u00eda \u201csoluciones \u00e1giles\u201d. La iron\u00eda no necesitaba subrayado. La mitad del peso eran im\u00e1genes situadas en secciones que muchos usuarios jam\u00e1s alcanzaban. Con compresi\u00f3n, formatos modernos y Lazy Loading, la p\u00e1gina no se volvi\u00f3 m\u00e1gica, pero dej\u00f3 de arrastrarse como una maleta sin ruedas.<\/p>\n<h2 id=\"cuando-no-usarlo\">Cu\u00e1ndo no debes usar carga diferida \ud83d\udeab<\/h2>\n<p>Aqu\u00ed aparece la parte menos c\u00f3moda: el Lazy Loading no debe aplicarse a todo. La optimizaci\u00f3n sin criterio es una forma elegante de romper cosas.<\/p>\n<p>No conviene cargar de forma diferida:<\/p>\n<ul>\n<li><strong>La imagen principal visible al cargar la p\u00e1gina<\/strong>, especialmente si es el elemento LCP.<\/li>\n<li><strong>Logotipos importantes<\/strong> que aparecen en la cabecera.<\/li>\n<li><strong>Im\u00e1genes above the fold<\/strong>, es decir, visibles sin hacer scroll.<\/li>\n<li><strong>Recursos cr\u00edticos para la estructura visual inicial<\/strong>.<\/li>\n<li><strong>Im\u00e1genes que afectan al dise\u00f1o si no tienen dimensiones reservadas<\/strong>, porque pueden provocar saltos visuales.<\/li>\n<\/ul>\n<p>Una imagen hero con <code>loading=\"lazy\"<\/code> es un cl\u00e1sico error moderno: suena sofisticado, pero puede empeorar el <strong>LCP<\/strong>. Es como pedirle al protagonista que espere en bambalinas mientras los figurantes ocupan el escenario.<\/p>\n<p>        <strong>Regla pr\u00e1ctica:<\/strong> si el recurso aparece en el primer pantallazo o es candidato a LCP, usa <code>loading=\"eager\"<\/code> o no declares <code>loading<\/code>, y considera <code>fetchpriority=\"high\"<\/code> solo para el elemento realmente prioritario.<\/p>\n<h2 id=\"html-nativo\">Implementaci\u00f3n con HTML nativo \ud83e\uddf1<\/h2>\n<p>La forma m\u00e1s simple y recomendable para im\u00e1genes e iframes es usar el atributo nativo <code>loading=\"lazy\"<\/code>. Est\u00e1 soportado por los navegadores modernos y no requiere librer\u00edas externas.<\/p>\n<h3>Imagen con carga diferida<\/h3>\n<pre><code>&lt;img\n  src=\"\/imagenes\/producto-800.jpg\"\n  srcset=\"\/imagenes\/producto-400.jpg 400w,\n          \/imagenes\/producto-800.jpg 800w,\n          \/imagenes\/producto-1200.jpg 1200w\"\n  sizes=\"(max-width: 768px) 100vw, 800px\"\n  width=\"800\"\n  height=\"533\"\n  alt=\"Detalle del producto sobre una mesa de madera\"\n  loading=\"lazy\"\n  decoding=\"async\"&gt;<\/code><\/pre>\n<p>Hay varios detalles importantes en este ejemplo:<\/p>\n<ul>\n<li><code>loading=\"lazy\"<\/code> indica al navegador que puede retrasar la carga.<\/li>\n<li><code>decoding=\"async\"<\/code> permite decodificar la imagen de forma as\u00edncrona, reduciendo bloqueos de renderizado.<\/li>\n<li><code>width<\/code> y <code>height<\/code> reservan espacio y ayudan a evitar <strong>Cumulative Layout Shift o CLS<\/strong>.<\/li>\n<li><code>srcset<\/code> y <code>sizes<\/code> permiten servir im\u00e1genes adaptadas a cada pantalla.<\/li>\n<\/ul>\n<h3>Iframe con carga diferida<\/h3>\n<pre><code>&lt;iframe\n  src=\"https:\/\/www.youtube.com\/embed\/VIDEO_ID\"\n  width=\"560\"\n  height=\"315\"\n  title=\"V\u00eddeo explicativo sobre optimizaci\u00f3n web\"\n  loading=\"lazy\"\n  allowfullscreen&gt;&lt;\/iframe&gt;<\/code><\/pre>\n<p>Esto resulta especialmente \u00fatil para v\u00eddeos de YouTube, mapas de Google Maps, embeds de calendarios o widgets externos. Los iframes suelen ser pesados, caprichosos y algo dram\u00e1ticos; tratarlos con distancia prudente es casi una virtud t\u00e9cnica.<\/p>\n<h3>Imagen principal: lo contrario de Lazy Loading<\/h3>\n<p>Para la imagen principal de una p\u00e1gina, especialmente en una landing page o entrada de blog, normalmente conviene hacer lo opuesto:<\/p>\n<pre><code>&lt;img\n  src=\"\/imagenes\/hero-1200.jpg\"\n  width=\"1200\"\n  height=\"675\"\n  alt=\"Panel de anal\u00edtica web mostrando m\u00e9tricas de rendimiento\"\n  loading=\"eager\"\n  fetchpriority=\"high\"\n  decoding=\"async\"&gt;<\/code><\/pre>\n<p><code>fetchpriority=\"high\"<\/code> puede ayudar al navegador a priorizar esa imagen. Pero \u00fasalo como sal fina, no como salsa industrial. Si marcas diez im\u00e1genes como prioritarias, ninguna lo es realmente.<\/p>\n<h2 id=\"javascript\">Lazy Loading con JavaScript e Intersection Observer \ud83d\udc40<\/h2>\n<p>El HTML nativo cubre muchos casos, pero no todos. Si necesitas cargar fondos CSS, aplicar animaciones, sustituir placeholders, controlar umbrales o dar soporte espec\u00edfico a ciertos patrones, puedes usar <strong>Intersection Observer<\/strong>.<\/p>\n<p>Esta API permite saber cu\u00e1ndo un elemento entra o se aproxima al \u00e1rea visible del navegador. Antes se hac\u00eda escuchando eventos de scroll, calculando posiciones a mano y rezando un poco. Intersection Observer es m\u00e1s limpio, m\u00e1s eficiente y menos propenso a convertir el scroll en una carraca.<\/p>\n<h3>Ejemplo b\u00e1sico para im\u00e1genes<\/h3>\n<p>Primero, el HTML:<\/p>\n<pre><code>&lt;img\n  src=\"\/imagenes\/placeholder.svg\"\n  data-src=\"\/imagenes\/foto-real.jpg\"\n  width=\"900\"\n  height=\"600\"\n  alt=\"Equipo trabajando en la optimizaci\u00f3n de un sitio web\"\n &gt;<\/code><\/pre>\n<p>Despu\u00e9s, el JavaScript:<\/p>\n<pre><code>document.addEventListener('DOMContentLoaded', function () {\n  const lazyImages = document.querySelectorAll('img.lazy-image[data-src]');\n\n  if ('IntersectionObserver' in window) {\n    const imageObserver = new IntersectionObserver(function (entries, observer) {\n      entries.forEach(function (entry) {\n        if (!entry.isIntersecting) return;\n\n        const img = entry.target;\n        img.src = img.dataset.src;\n        img.removeAttribute('data-src');\n        img.classList.add('is-loaded');\n\n        observer.unobserve(img);\n      });\n    }, {\n      root: null,\n      rootMargin: '250px 0px',\n      threshold: 0.01\n    });\n\n    lazyImages.forEach(function (img) {\n      imageObserver.observe(img);\n    });\n  } else {\n    lazyImages.forEach(function (img) {\n      img.src = img.dataset.src;\n      img.removeAttribute('data-src');\n    });\n  }\n});<\/code><\/pre>\n<p>El valor <code>rootMargin: '250px 0px'<\/code> hace que la imagen empiece a cargarse antes de entrar en pantalla. Esto evita que el usuario vea espacios vac\u00edos si hace scroll r\u00e1pido. Es como encender las luces de una habitaci\u00f3n justo antes de cruzar la puerta.<\/p>\n<h3>Con efecto suave al cargar<\/h3>\n<pre><code>.lazy-image {\n  opacity: 0;\n  transition: opacity 280ms ease;\n}\n\n.lazy-image.is-loaded {\n  opacity: 1;\n}<\/code><\/pre>\n<p>Una transici\u00f3n sobria puede mejorar la sensaci\u00f3n de fluidez. Pero cuidado con convertir cada imagen en una \u00f3pera. La animaci\u00f3n debe servir al contenido, no pedir aplausos.<\/p>\n<h2 id=\"wordpress\">C\u00f3mo programar Lazy Loading en WordPress sin plugins \ud83d\udee0\ufe0f<\/h2>\n<p>WordPress incorpor\u00f3 carga diferida nativa para im\u00e1genes en la versi\u00f3n 5.5 y posteriormente extendi\u00f3 mejoras para iframes y prioridades de carga. En versiones recientes, WordPress intenta ser m\u00e1s inteligente: no todo se trata igual, y eso es bueno. Aun as\u00ed, hay casos donde un desarrollador necesita ajustar el comportamiento desde el tema, un tema hijo o un peque\u00f1o mu-plugin propio.<\/p>\n<p>La v\u00eda correcta no es modificar el n\u00facleo de WordPress. Jam\u00e1s. Eso ser\u00eda como arreglar una gotera perforando el tejado con entusiasmo. Lo razonable es trabajar con filtros en <code>functions.php<\/code> o, mejor a\u00fan, en un plugin propio m\u00ednimo si se busca portabilidad. Como el objetivo aqu\u00ed es hacerlo sin plugins de terceros, usaremos c\u00f3digo controlado por nosotros.<\/p>\n<h3>1. A\u00f1adir atributos a im\u00e1genes generadas con funciones de WordPress<\/h3>\n<p>Cuando usas funciones como <code>wp_get_attachment_image()<\/code>, puedes ajustar atributos mediante el filtro <code>wp_get_attachment_image_attributes<\/code>.<\/p>\n<pre><code>add_filter('wp_get_attachment_image_attributes', function ($attr, $attachment, $size) {\n    if (is_admin()) {\n        return $attr;\n    }\n\n    if (empty($attr['loading'])) {\n        $attr['loading'] = 'lazy';\n    }\n\n    $attr['decoding'] = 'async';\n\n    return $attr;\n}, 10, 3);<\/code><\/pre>\n<p>Este fragmento a\u00f1ade <code>loading=\"lazy\"<\/code> y <code>decoding=\"async\"<\/code> a im\u00e1genes generadas por WordPress cuando no tengan ya un valor definido.<\/p>\n<p>        <strong>Atenci\u00f3n:<\/strong> no fuerces <code>loading=\"lazy\"<\/code> en todas las im\u00e1genes sin excepci\u00f3n. La imagen principal o imagen destacada visible al inicio puede necesitar <code>loading=\"eager\"<\/code> y <code>fetchpriority=\"high\"<\/code>.<\/p>\n<h3>2. Marcar la imagen hero como prioritaria en una plantilla<\/h3>\n<p>Si est\u00e1s editando una plantilla de tema \u2014por ejemplo, <code>single.php<\/code>, <code>front-page.php<\/code> o un bloque personalizado\u2014 puedes imprimir la imagen destacada con atributos espec\u00edficos:<\/p>\n<pre><code>if (has_post_thumbnail()) {\n    echo get_the_post_thumbnail(get_the_ID(), 'full', array(\n        'class'         =&gt; 'hero__image',\n        'loading'       =&gt; 'eager',\n        'fetchpriority' =&gt; 'high',\n        'decoding'      =&gt; 'async',\n        'alt'           =&gt; esc_attr(get_the_title())\n    ));\n}<\/code><\/pre>\n<p>Este patr\u00f3n es \u00fatil para mejorar el <strong>Largest Contentful Paint<\/strong>. El navegador recibe una se\u00f1al clara: esta imagen importa ahora. No dentro de tres scrolls. Ahora.<\/p>\n<h3>3. Evitar Lazy Loading en la primera imagen del contenido<\/h3>\n<p>En algunas entradas, la primera imagen dentro del contenido puede ser el elemento visual m\u00e1s importante. WordPress ya aplica ciertas heur\u00edsticas en versiones modernas, pero si necesitas controlar este comportamiento, puedes usar el filtro <code>wp_img_tag_add_loading_attr<\/code>.<\/p>\n<pre><code>add_filter('wp_img_tag_add_loading_attr', function ($value, $image, $context) {\n    static $content_image_count = 0;\n\n    if (is_admin()) {\n        return $value;\n    }\n\n    if ('the_content' === $context) {\n        $content_image_count++;\n\n        if (1 === $content_image_count && is_singular()) {\n            return false;\n        }\n    }\n\n    return $value;\n}, 10, 3);<\/code><\/pre>\n<p>Este ejemplo elimina el atributo <code>loading<\/code> de la primera imagen del contenido en vistas singulares. Es una base, no una ley universal. En archivos, loops complejos o constructores visuales, conviene revisar el comportamiento real.<\/p>\n<h3>4. A\u00f1adir Lazy Loading a iframes en contenido antiguo<\/h3>\n<p>Si tienes publicaciones antiguas con iframes sin el atributo <code>loading<\/code>, puedes procesar el contenido con cuidado:<\/p>\n<pre><code>add_filter('the_content', function ($content) {\n    if (is_admin() || false === strpos($content, '&lt;iframe')) {\n        return $content;\n    }\n\n    return preg_replace_callback('\/&lt;iframe\\s(.*?)&gt;\/i', function ($matches) {\n        $iframe = $matches[0];\n\n        if (false !== strpos($iframe, ' loading=')) {\n            return $iframe;\n        }\n\n        return str_replace('&lt;iframe ', '&lt;iframe loading=\"lazy\" ', $iframe);\n    }, $content);\n});<\/code><\/pre>\n<p>Este c\u00f3digo es pr\u00e1ctico, aunque no perfecto. Si trabajas en un sitio grande o con HTML muy heterog\u00e9neo, una soluci\u00f3n basada en <code>DOMDocument<\/code> puede ser m\u00e1s robusta. Las expresiones regulares con HTML son como gatos con corbata: pueden parecer civilizadas, pero no siempre obedecen.<\/p>\n<h3>5. Crear un shortcode simple para iframes con carga diferida<\/h3>\n<p>Si quieres estandarizar embeds sin depender de plugins, puedes crear un shortcode:<\/p>\n<pre><code>add_shortcode('iframe_lazy', function ($atts) {\n    $atts = shortcode_atts(array(\n        'src'    =&gt; '',\n        'title'  =&gt; 'Contenido incrustado',\n        'width'  =&gt; '560',\n        'height' =&gt; '315',\n    ), $atts);\n\n    if (empty($atts['src'])) {\n        return '';\n    }\n\n    return sprintf(\n        '&lt;iframe src=\"%s\" title=\"%s\" width=\"%s\" height=\"%s\" loading=\"lazy\" allowfullscreen&gt;&lt;\/iframe&gt;',\n        esc_url($atts['src']),\n        esc_attr($atts['title']),\n        esc_attr($atts['width']),\n        esc_attr($atts['height'])\n    );\n});<\/code><\/pre>\n<p>Uso en el editor:<\/p>\n<pre><code>[iframe_lazy src=\"https:\/\/www.youtube.com\/embed\/VIDEO_ID\" title=\"V\u00eddeo sobre rendimiento web\"]<\/code><\/pre>\n<h2 id=\"fondos-css\">Carga diferida para fondos CSS \ud83c\udf04<\/h2>\n<p>El atributo <code>loading=\"lazy\"<\/code> no funciona con im\u00e1genes de fondo definidas en CSS mediante <code>background-image<\/code>. Y aqu\u00ed muchos sitios tropiezan. Las im\u00e1genes decorativas gigantes suelen esconderse en secciones con fondo, banners, bloques promocionales o sliders. Bonitas, s\u00ed. Ligeras, no siempre.<\/p>\n<p>Para diferir fondos, podemos usar <code>data-bg<\/code> e Intersection Observer.<\/p>\n<h3>HTML<\/h3>\n<pre><code>&lt;section\n \n  data-bg=\"\/wp-content\/uploads\/promo-rendimiento.jpg\"&gt;\n  &lt;h2&gt;Optimizaci\u00f3n web profesional&lt;\/h2&gt;\n  &lt;p&gt;Mejora la velocidad de tu sitio sin sacrificar dise\u00f1o.&lt;\/p&gt;\n&lt;\/section&gt;<\/code><\/pre>\n<h3>CSS<\/h3>\n<pre><code>.promo {\n  min-height: 420px;\n  background-color: #0f172a;\n  background-size: cover;\n  background-position: center;\n}\n\n.lazy-bg.is-loaded {\n  transition: opacity 250ms ease;\n}<\/code><\/pre>\n<h3>JavaScript<\/h3>\n<pre><code>document.addEventListener('DOMContentLoaded', function () {\n  const lazyBackgrounds = document.querySelectorAll('.lazy-bg[data-bg]');\n\n  if ('IntersectionObserver' in window) {\n    const bgObserver = new IntersectionObserver(function (entries, observer) {\n      entries.forEach(function (entry) {\n        if (!entry.isIntersecting) return;\n\n        const element = entry.target;\n        element.style.backgroundImage = 'url(\"' + element.dataset.bg + '\")';\n        element.classList.add('is-loaded');\n        element.removeAttribute('data-bg');\n\n        observer.unobserve(element);\n      });\n    }, {\n      rootMargin: '300px 0px',\n      threshold: 0.01\n    });\n\n    lazyBackgrounds.forEach(function (element) {\n      bgObserver.observe(element);\n    });\n  } else {\n    lazyBackgrounds.forEach(function (element) {\n      element.style.backgroundImage = 'url(\"' + element.dataset.bg + '\")';\n      element.removeAttribute('data-bg');\n    });\n  }\n});<\/code><\/pre>\n<p>Si el fondo es meramente decorativo, perfecto. Si transmite informaci\u00f3n importante, considera usar una imagen real con <code>alt<\/code>. La accesibilidad no es un adorno moral para poner al final del proyecto; es parte de la arquitectura.<\/p>\n<h2 id=\"seo\">SEO, accesibilidad y Core Web Vitals \ud83d\udd0e<\/h2>\n<p>Una preocupaci\u00f3n frecuente es si el Lazy Loading afecta al SEO. La respuesta corta: <strong>bien implementado, no deber\u00eda perjudicarlo<\/strong>. Googlebot renderiza JavaScript y entiende el atributo nativo <code>loading=\"lazy\"<\/code>. Sin embargo, hay matices.<\/p>\n<h3>Buenas pr\u00e1cticas SEO para carga diferida<\/h3>\n<ul>\n<li>Usa siempre atributos <code>alt<\/code> descriptivos en im\u00e1genes relevantes.<\/li>\n<li>No ocultes contenido esencial detr\u00e1s de interacciones innecesarias.<\/li>\n<li>Evita depender exclusivamente de JavaScript fr\u00e1gil para mostrar im\u00e1genes cr\u00edticas.<\/li>\n<li>Incluye dimensiones <code>width<\/code> y <code>height<\/code> para reducir CLS.<\/li>\n<li>No apliques Lazy Loading al contenido principal visible al inicio.<\/li>\n<li>Comprueba la p\u00e1gina renderizada en Google Search Console cuando sea necesario.<\/li>\n<\/ul>\n<p>Para accesibilidad, el Lazy Loading debe ser invisible. El usuario no deber\u00eda notar una web que aparece a trompicones, con huecos que saltan como peces en cubierta. Reserva espacio, usa placeholders discretos y evita animaciones agresivas.<\/p>\n<h3>Relaci\u00f3n con Core Web Vitals<\/h3>\n<table>\n<thead>\n<tr>\n<th>M\u00e9trica<\/th>\n<th>C\u00f3mo ayuda Lazy Loading<\/th>\n<th>C\u00f3mo puede perjudicar<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>LCP<\/strong><\/td>\n<td>Reduce competencia de recursos no cr\u00edticos.<\/td>\n<td>Si aplicas lazy a la imagen LCP, puede retrasarla.<\/td>\n<\/tr>\n<tr>\n<td><strong>CLS<\/strong><\/td>\n<td>Puede ser neutro si reservas dimensiones.<\/td>\n<td>Provoca saltos si las im\u00e1genes aparecen sin espacio reservado.<\/td>\n<\/tr>\n<tr>\n<td><strong>INP<\/strong><\/td>\n<td>Menos carga inicial puede reducir presi\u00f3n sobre el hilo principal.<\/td>\n<td>JavaScript mal escrito puede a\u00f1adir trabajo innecesario.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>El rendimiento web es una disciplina de contrastes: cargar menos para mostrar m\u00e1s r\u00e1pido; retrasar para adelantar; ocultar temporalmente para revelar mejor. Esa ant\u00edtesis, bien entendida, es el coraz\u00f3n de la carga diferida.<\/p>\n<h2 id=\"errores\">Errores frecuentes al implementar Lazy Loading \ud83e\uddef<\/h2>\n<p>La carga diferida parece simple, y lo es. Hasta que deja de serlo. Estos son los tropiezos m\u00e1s habituales:<\/p>\n<h3>1. Aplicarlo a la imagen principal<\/h3>\n<p>Ya lo hemos dicho, pero merece repetirse con otra m\u00fasica: no cargues en diferido la imagen m\u00e1s importante del primer pantallazo. Si tu LCP es una imagen hero y la marcas como <code>lazy<\/code>, est\u00e1s poniendo una zancadilla a tu propia m\u00e9trica.<\/p>\n<h3>2. No definir ancho y alto<\/h3>\n<p>Sin <code>width<\/code> y <code>height<\/code>, el navegador no puede reservar correctamente el espacio. Cuando la imagen carga, empuja el contenido. El usuario iba leyendo tranquilamente y, de pronto, el p\u00e1rrafo salta como si hubiera visto un rat\u00f3n.<\/p>\n<h3>3. Usar placeholders demasiado pesados<\/h3>\n<p>Un placeholder no deber\u00eda pesar casi tanto como la imagen real. Parece obvio. No siempre lo es. Usa colores s\u00f3lidos, SVG ligeros, miniaturas muy comprimidas o t\u00e9cnicas de blur con moderaci\u00f3n.<\/p>\n<h3>4. Depender de librer\u00edas enormes<\/h3>\n<p>Si usas una biblioteca de 40 KB para diferir tres im\u00e1genes, quiz\u00e1s est\u00e1s resolviendo un problema peque\u00f1o con una maquinaria de puerto industrial. Intersection Observer suele ser suficiente.<\/p>\n<h3>5. No probar en m\u00f3viles reales<\/h3>\n<p>El escritorio miente con elegancia. Una web puede parecer r\u00e1pida en fibra \u00f3ptica y sufrir en un m\u00f3vil de gama media con red irregular. Prueba siempre con throttling y, si puedes, con dispositivos reales.<\/p>\n<h3>6. Olvidar im\u00e1genes en sliders y constructores visuales<\/h3>\n<p>Muchos sliders cargan todas las diapositivas desde el inicio. Algunos constructores visuales generan estructuras pesadas con fondos inline. Conviene revisar el HTML final, no el ideal que imaginamos.<\/p>\n<h2>Lazy Loading y formatos modernos de imagen \ud83d\uddbc\ufe0f<\/h2>\n<p>La carga diferida funciona mejor cuando se combina con otras optimizaciones. No es sustituto de comprimir im\u00e1genes ni de usar formatos modernos. Si difieres una imagen de 5 MB, solo est\u00e1s posponiendo el golpe. M\u00e1s tarde doler\u00e1 igual.<\/p>\n<p>Recomendaciones pr\u00e1cticas:<\/p>\n<ul>\n<li>Usa <strong>WebP<\/strong> o <strong>AVIF<\/strong> cuando sea viable.<\/li>\n<li>Sirve im\u00e1genes responsivas con <code>srcset<\/code> y <code>sizes<\/code>.<\/li>\n<li>Comprime sin destruir la calidad visual.<\/li>\n<li>Evita subir im\u00e1genes de 4000 px si se mostrar\u00e1n a 800 px.<\/li>\n<li>Utiliza CDN si tu audiencia est\u00e1 distribuida geogr\u00e1ficamente.<\/li>\n<\/ul>\n<p>Ejemplo con <code>picture<\/code>:<\/p>\n<pre><code>&lt;picture&gt;\n  &lt;source\n    type=\"image\/avif\"\n    srcset=\"\/imagenes\/oficina-600.avif 600w,\n            \/imagenes\/oficina-1200.avif 1200w\"&gt;\n\n  &lt;source\n    type=\"image\/webp\"\n    srcset=\"\/imagenes\/oficina-600.webp 600w,\n            \/imagenes\/oficina-1200.webp 1200w\"&gt;\n\n  &lt;img\n    src=\"\/imagenes\/oficina-1200.jpg\"\n    srcset=\"\/imagenes\/oficina-600.jpg 600w,\n            \/imagenes\/oficina-1200.jpg 1200w\"\n    sizes=\"(max-width: 768px) 100vw, 1200px\"\n    width=\"1200\"\n    height=\"800\"\n    alt=\"Oficina moderna con pantallas de an\u00e1lisis web\"\n    loading=\"lazy\"\n    decoding=\"async\"&gt;\n&lt;\/picture&gt;<\/code><\/pre>\n<p>El navegador elegir\u00e1 el formato m\u00e1s eficiente que soporte. La imagen se cargar\u00e1 en diferido si no es prioritaria. Sencillo, robusto, elegante.<\/p>\n<h2>Implementaci\u00f3n avanzada: patr\u00f3n h\u00edbrido recomendado \ud83e\udde9<\/h2>\n<p>En un proyecto profesional, normalmente conviene usar una estrategia mixta:<\/p>\n<ol>\n<li><strong>HTML nativo<\/strong> para im\u00e1genes e iframes comunes.<\/li>\n<li><strong>Exclusi\u00f3n manual<\/strong> para recursos cr\u00edticos above the fold.<\/li>\n<li><strong>Intersection Observer<\/strong> para fondos CSS y casos especiales.<\/li>\n<li><strong>Dimensiones reservadas<\/strong> para evitar saltos de dise\u00f1o.<\/li>\n<li><strong>Auditor\u00eda posterior<\/strong> con herramientas de rendimiento.<\/li>\n<\/ol>\n<p>Un esquema razonable ser\u00eda:<\/p>\n<pre><code>&lt;!-- Imagen principal: prioritaria --&gt;\n&lt;img\n  src=\"\/imagenes\/hero.webp\"\n  width=\"1400\"\n  height=\"788\"\n  alt=\"Dashboard de rendimiento web\"\n  loading=\"eager\"\n  fetchpriority=\"high\"\n  decoding=\"async\"&gt;\n\n&lt;!-- Imagen secundaria: diferida --&gt;\n&lt;img\n  src=\"\/imagenes\/caso-estudio.webp\"\n  width=\"900\"\n  height=\"600\"\n  alt=\"Gr\u00e1fico de mejora de velocidad\"\n  loading=\"lazy\"\n  decoding=\"async\"&gt;\n\n&lt;!-- Iframe secundario: diferido --&gt;\n&lt;iframe\n  src=\"https:\/\/www.google.com\/maps\/embed?pb=...\"\n  width=\"600\"\n  height=\"450\"\n  title=\"Ubicaci\u00f3n de la oficina\"\n  loading=\"lazy\"&gt;&lt;\/iframe&gt;<\/code><\/pre>\n<h2 id=\"pruebas\">C\u00f3mo comprobar que el Lazy Loading funciona \ud83e\uddea<\/h2>\n<p>No basta con a\u00f1adir atributos y confiar. La fe es respetable en otros \u00e1mbitos; en rendimiento web, mejor medir.<\/p>\n<h3>1. Chrome DevTools<\/h3>\n<ol>\n<li>Abre la p\u00e1gina en Chrome.<\/li>\n<li>Presiona <span>F12<\/span> o clic derecho y \u201cInspeccionar\u201d.<\/li>\n<li>Ve a la pesta\u00f1a <strong>Network<\/strong>.<\/li>\n<li>Filtra por <strong>Img<\/strong> o <strong>Media<\/strong>.<\/li>\n<li>Recarga la p\u00e1gina.<\/li>\n<li>Observa qu\u00e9 im\u00e1genes se descargan al inicio y cu\u00e1les aparecen al hacer scroll.<\/li>\n<\/ol>\n<p>Si todas las im\u00e1genes de una p\u00e1gina larga se descargan inmediatamente, algo no est\u00e1 funcionando o est\u00e1n demasiado cerca del viewport seg\u00fan el criterio del navegador.<\/p>\n<h3>2. Lighthouse<\/h3>\n<p>Lighthouse puede detectar im\u00e1genes fuera de pantalla que se cargan sin necesidad. Revisa especialmente:<\/p>\n<ul>\n<li><strong>Defer offscreen images<\/strong>.<\/li>\n<li><strong>Largest Contentful Paint element<\/strong>.<\/li>\n<li><strong>Cumulative Layout Shift<\/strong>.<\/li>\n<li><strong>Properly size images<\/strong>.<\/li>\n<li><strong>Serve images in next-gen formats<\/strong>.<\/li>\n<\/ul>\n<h3>3. PageSpeed Insights<\/h3>\n<p>PageSpeed Insights combina datos de laboratorio con datos reales del Chrome User Experience Report cuando existen. Es especialmente \u00fatil para revisar <strong>Core Web Vitals<\/strong> en m\u00f3viles.<\/p>\n<h3>4. WebPageTest<\/h3>\n<p>WebPageTest permite ver cascadas de red, filmstrips y comportamiento bajo distintas condiciones. Para auditor\u00edas serias, sigue siendo una herramienta magn\u00edfica. Algo \u00e1spera, quiz\u00e1. Como las buenas herramientas de taller.<\/p>\n<h2>Checklist profesional antes de publicar \u2705<\/h2>\n<ul>\n<li>La imagen LCP no usa <code>loading=\"lazy\"<\/code>.<\/li>\n<li>Solo un recurso cr\u00edtico, si corresponde, usa <code>fetchpriority=\"high\"<\/code>.<\/li>\n<li>Las im\u00e1genes bajo el primer pantallazo usan <code>loading=\"lazy\"<\/code>.<\/li>\n<li>Los iframes secundarios usan <code>loading=\"lazy\"<\/code>.<\/li>\n<li>Todas las im\u00e1genes tienen <code>width<\/code> y <code>height<\/code> o espacio reservado con CSS.<\/li>\n<li>Las im\u00e1genes relevantes tienen texto <code>alt<\/code> adecuado.<\/li>\n<li>Los fondos CSS pesados se cargan con Intersection Observer.<\/li>\n<li>Los placeholders son ligeros.<\/li>\n<li>Se ha probado en m\u00f3vil y con red lenta simulada.<\/li>\n<li>Se ha revisado el impacto en LCP, CLS e INP.<\/li>\n<\/ul>\n<h2>Preguntas frecuentes sobre Lazy Loading \u2753<\/h2>\n<h3>\u00bfEl Lazy Loading mejora siempre la velocidad?<\/h3>\n<p>No siempre. Mejora la carga inicial cuando hay recursos no cr\u00edticos fuera de pantalla. Si la p\u00e1gina tiene pocas im\u00e1genes o si se aplica mal a elementos prioritarios, el beneficio puede ser peque\u00f1o o incluso negativo.<\/p>\n<h3>\u00bfNecesito JavaScript para usar Lazy Loading?<\/h3>\n<p>Para im\u00e1genes e iframes comunes, no. Puedes usar <code>loading=\"lazy\"<\/code>. JavaScript es \u00fatil para fondos CSS, efectos personalizados, compatibilidad espec\u00edfica o control avanzado.<\/p>\n<h3>\u00bfWordPress ya lo hace autom\u00e1ticamente?<\/h3>\n<p>En gran parte, s\u00ed. WordPress a\u00f1ade carga diferida nativa a muchas im\u00e1genes e iframes desde versiones modernas. Pero no siempre conoce tu intenci\u00f3n visual. Una plantilla bien construida puede marcar la diferencia entre una optimizaci\u00f3n gen\u00e9rica y una optimizaci\u00f3n realmente fina.<\/p>\n<h3>\u00bfPuede afectar al posicionamiento SEO?<\/h3>\n<p>Bien implementado, no deber\u00eda perjudicar el SEO. Al contrario, puede mejorar se\u00f1ales de experiencia de usuario relacionadas con rendimiento. Lo importante es que el contenido sea accesible, rastreable y no dependa de trucos fr\u00e1giles.<\/p>\n<h3>\u00bfQu\u00e9 diferencia hay entre <code>loading=\"lazy\"<\/code> y <code>decoding=\"async\"<\/code>?<\/h3>\n<p><code>loading=\"lazy\"<\/code> decide cu\u00e1ndo descargar la imagen. <code>decoding=\"async\"<\/code> indica c\u00f3mo decodificarla para no bloquear innecesariamente el renderizado. Son atributos complementarios, no equivalentes.<\/p>\n<h3>\u00bfDebo usar Lazy Loading en una tienda online?<\/h3>\n<p>S\u00ed, especialmente en listados largos de productos, galer\u00edas secundarias y recomendaciones. Pero la imagen principal del producto visible al cargar debe tratarse con prioridad. En comercio electr\u00f3nico, cada d\u00e9cima de segundo puede ser una moneda que cae o se pierde.<\/p>\n<h2>Para cerrar: cargar menos, mostrar mejor \ud83c\udf3f<\/h2>\n<p>El Lazy Loading no es una moda ni un barniz t\u00e9cnico para impresionar en una auditor\u00eda. Es una forma sensata de administrar la atenci\u00f3n del navegador. Primero lo esencial. Despu\u00e9s lo complementario. En ese orden sencillo se esconde buena parte de la optimizaci\u00f3n web moderna.<\/p>\n<p>Programarlo sin plugins es perfectamente posible: HTML nativo para im\u00e1genes e iframes, Intersection Observer para casos especiales, filtros de WordPress para adaptar el comportamiento y una regla de oro que conviene no olvidar: <strong>no difieras lo que el usuario necesita ver ahora<\/strong>.<\/p>\n<p>Una web r\u00e1pida no es la que lo carga todo con prisa, sino la que sabe esperar. Como un buen editor, corta lo innecesario al principio para que lo importante respire. Y en tiempos de p\u00e1ginas obesas, scripts impacientes e im\u00e1genes descomunales, esa sobriedad casi parece revolucionaria.<\/p>\n<p>Palabras clave relacionadas: Lazy Loading, carga diferida, optimizaci\u00f3n web, rendimiento WordPress, Core Web Vitals, mejorar velocidad web, im\u00e1genes WebP, Intersection Observer, WordPress sin plugins.<\/p>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>\u00bfQu\u00e9 es el \u201cLazy Loading\u201d o carga diferida y c\u00f3mo programarlo sin usar plugins? \ud83d\ude80<\/p>\n","protected":false},"author":1,"featured_media":3894,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_seopress_titles_title":"","_seopress_titles_desc":"","_seopress_robots_index":"","_seopress_robots_follow":"","_seopress_robots_imageindex":"","_seopress_robots_snippet":"","_seopress_robots_primary_cat":"","_seopress_robots_breadcrumbs":"","_seopress_robots_freeze_modified_date":"","_seopress_robots_custom_modified_date":"","_seopress_robots_canonical":"","_seopress_social_fb_title":"","_seopress_social_fb_desc":"","_seopress_social_fb_img":"","_seopress_social_fb_img_attachment_id":0,"_seopress_social_fb_img_width":0,"_seopress_social_fb_img_height":0,"_seopress_social_twitter_title":"","_seopress_social_twitter_desc":"","_seopress_social_twitter_img":"","_seopress_social_twitter_img_attachment_id":0,"_seopress_social_twitter_img_width":0,"_seopress_social_twitter_img_height":0,"_seopress_redirections_value":"","_seopress_redirections_enabled":"","_seopress_redirections_enabled_regex":"","_seopress_redirections_logged_status":"","_seopress_redirections_param":"","_seopress_redirections_type":0,"_seopress_analysis_target_kw":"","_seopress_news_disabled":"","_seopress_video_disabled":"","_seopress_video":[],"_seopress_pro_schemas_manual":[],"_seopress_pro_rich_snippets_disable_all":"","_seopress_pro_rich_snippets_disable":[],"_seopress_pro_schemas":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-3895","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mantenimiento"],"_links":{"self":[{"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/posts\/3895","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/comments?post=3895"}],"version-history":[{"count":1,"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/posts\/3895\/revisions"}],"predecessor-version":[{"id":3896,"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/posts\/3895\/revisions\/3896"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/media\/3894"}],"wp:attachment":[{"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/media?parent=3895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/categories?post=3895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mantenimientoweb.pro\/blog\/wp-json\/wp\/v2\/tags?post=3895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}