// ── Tell LiteSpeed to never lazy-load WooCommerce product images ──────────────
add_filter('litespeed_media_lazy_img_cls_excludes', function($excludes) {
if (!is_array($excludes)) $excludes = [];
$excludes[] = 'woo-entry-image-main';
$excludes[] = 'wp-post-image';
return $excludes;
});
// ── Remove lazy loading from first WooCommerce product image ──────────────────
add_action('template_redirect', function() {
ob_start(function($html) {
static $done = false;
if ($done) return $html;
$html = preg_replace_callback(
'/
]*class="[^"]*woo-entry-image-main[^"]*"[^>]*)>/i',
function($m) use (&$done) {
if ($done) return $m[0];
$attrs = $m[1];
$attrs = str_replace(' loading="lazy"', '', $attrs);
$attrs = str_replace(" loading='lazy'", '', $attrs);
$attrs = preg_replace('/\s*data-lazyloaded="[^"]*"/', '', $attrs);
if (strpos($attrs, 'fetchpriority') === false) {
$attrs .= ' fetchpriority="high"';
}
$done = true;
return '
';
},
$html
);
return $html;
});
}, 1);
// ── Remove lazy loading from first WooCommerce product image ──────────────────
add_action('template_redirect', function() {
ob_start(function($html) {
static $done = false;
if ($done) return $html;
$html = preg_replace_callback(
'/
]*class="[^"]*woo-entry-image-main[^"]*"[^>]*)>/i',
function($m) use (&$done) {
if ($done) return $m[0];
$attrs = $m[1];
$attrs = str_replace(' loading="lazy"', '', $attrs);
$attrs = str_replace(" loading='lazy'", '', $attrs);
$attrs = preg_replace('/\s*data-lazyloaded="[^"]*"/', '', $attrs);
if (strpos($attrs, 'fetchpriority') === false) {
$attrs .= ' fetchpriority="high"';
}
$done = true;
return '
';
},
$html
);
return $html;
});
}, 1);
// ── Fix lazy loading v2 — simpler regex ───────────────────────────────────────
add_action('template_redirect', function() {
ob_start(function($html) {
// Remove first occurrence of loading="lazy" from woo-entry-image-main
$count = 0;
return preg_replace_callback(
'/
]*woo-entry-image-main[^>]*>/i',
function($m) use (&$count) {
if ($count > 0) return $m[0];
$tag = preg_replace('/\s+loading=["\']lazy["\']/i', '', $m[0]);
$tag = str_replace(' decoding="async"', ' decoding="async" fetchpriority="high"', $tag);
$count++;
return $tag;
},
$html
);
});
}, 2);
// ── Remove lazy from first product image using WP filter ─────────────────────
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment, $size) {
static $count = 0;
if ($count > 0) return $attr;
// Check if this is a WooCommerce product thumbnail
if (isset($attr['class']) && strpos($attr['class'], 'woo-entry-image-main') !== false) {
$attr['loading'] = 'eager';
$attr['fetchpriority'] = 'high';
$count++;
}
return $attr;
}, 99, 3);
// ── WooCommerce specific image eager loading ──────────────────────────────────
add_filter('woocommerce_product_loop_start', function($html) {
// Flag that we're in the first product loop
global $abh_first_product_done;
$abh_first_product_done = false;
return $html;
});
add_filter('woocommerce_thumbnail_size', function($size) {
global $abh_first_product_done;
if (!$abh_first_product_done) {
add_filter('wp_get_attachment_image_attributes', function($attr) {
global $abh_first_product_done;
if (!$abh_first_product_done) {
$attr['loading'] = 'eager';
$attr['fetchpriority'] = 'high';
$abh_first_product_done = true;
}
return $attr;
}, 999);
}
return $size;
});
// ── Fix first product image loading via wp_get_attachment_image_attributes ────
remove_all_filters('wp_get_attachment_image_attributes', 999);
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment, $size) {
static $fixed = false;
if ($fixed) return $attr;
$class = isset($attr['class']) ? $attr['class'] : '';
if (strpos($class, 'woo-entry-image-main') !== false) {
$attr['loading'] = 'eager';
$attr['fetchpriority'] = 'high';
$fixed = true;
}
return $attr;
}, 9999, 3);