fix(css): collapse ad slots initially to prevent layout shift

- Slots start with max-height:0, opacity:0, margin:0 (no visual space)
- Only expand when AdSense confirms filled status
- Use transition for smooth appearance
- Prevents layout shift when unfilled slots are hidden
- Combined with larger rootMargin (1000px) slots are pre-loaded
  before entering viewport, eliminating visible collapse

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-12-10 17:02:29 -06:00
parent 88103a774b
commit a4f63145dd
3 changed files with 48 additions and 25 deletions

View File

@@ -4,7 +4,11 @@
"Bash(mkdir:*)",
"mcp__serena__activate_project",
"mcp__serena__find_symbol",
"Bash(ssh:*)"
"Bash(ssh:*)",
"Bash(php:*)",
"mcp__playwright__browser_console_messages",
"mcp__playwright__browser_evaluate",
"mcp__playwright__browser_navigate"
]
}
}

View File

@@ -66,36 +66,55 @@ final class AdsensePlacementRenderer
// 4. Generar CSS (usando CSSGeneratorService)
$lazyEnabled = ($settings['behavior']['lazy_loading_enabled'] ?? true) === true;
// Nota: Para lazy loading usamos min-height:1px para que IntersectionObserver
// pueda detectar el elemento. Con display:none o height:0, IO no puede observar
// elementos porque tienen dimensiones 0x0 en el DOM.
// El contenido se oculta con visibility:hidden hasta que se active el slot.
$css = $this->cssGenerator->generate(
".roi-ad-slot",
[
'visibility' => $lazyEnabled ? 'hidden' : 'visible',
'min_height' => $lazyEnabled ? '1px' : 'auto',
'width' => '100%',
'min_width' => '300px',
// Estrategia para evitar layout shift:
// - Los slots inician colapsados (max-height:0) sin ocupar espacio visual
// - Usamos max-height en vez de height para que IO pueda detectarlos
// - Se pre-cargan con rootMargin grande (1000px) antes de ser visibles
// - Solo se expanden cuando AdSense confirma que hay anuncio (filled)
// - Si no hay anuncio (unfilled), permanecen colapsados
// - Esto evita que el usuario vea espacios que luego desaparecen
if ($lazyEnabled) {
$css = $this->cssGenerator->generate(
".roi-ad-slot",
[
'max_height' => '0',
'overflow' => 'hidden',
'opacity' => '0',
'width' => '100%',
'min_width' => '300px',
'text_align' => 'center',
'margin' => '0',
'padding' => '0',
'transition' => 'max-height 0.3s ease, opacity 0.3s ease, margin 0.3s ease',
]
);
// Slots con anuncio confirmado: se expanden y muestran
$css .= $this->cssGenerator->generate('.roi-ad-slot.roi-ad-filled', [
'max_height' => '600px',
'opacity' => '1',
'overflow' => 'visible',
'margin_top' => '1.5rem',
'margin_bottom' => '1.5rem',
'text_align' => 'center',
]
);
// CSS para slots con lazy loading que reciben contenido
if ($lazyEnabled) {
$css .= $this->cssGenerator->generate('.roi-ad-slot.roi-ad-filled', [
'visibility' => 'visible',
'min_height' => 'auto',
]);
// Slots vacios: permanecen colapsados sin ocupar espacio
$css .= $this->cssGenerator->generate('.roi-ad-slot.roi-ad-empty', [
'visibility' => 'hidden',
'min_height' => '0',
'height' => '0',
'max_height' => '0',
'opacity' => '0',
'margin' => '0',
'padding' => '0',
]);
} else {
// Modo legacy: slots siempre visibles
$css = $this->cssGenerator->generate(
".roi-ad-slot",
[
'width' => '100%',
'min_width' => '300px',
'margin_top' => '1.5rem',
'margin_bottom' => '1.5rem',
'text_align' => 'center',
]
);
}
// 5. Generar HTML del anuncio

View File

@@ -18,7 +18,7 @@ if (!defined('ABSPATH')) {
}
// Definir constante de versión del tema
define('ROI_VERSION', '1.0.24');
define('ROI_VERSION', '1.0.25');
// =============================================================================
// 1. CARGAR AUTOLOADER MANUAL