Tutorial WordPress: Crear una cabecera con sombra que aparece solo al hacer scroll

·

·

Introducción

En este tutorial completo aprenderás a crear una cabecera en WordPress que muestre una sombra (box-shadow) únicamente cuando el usuario hace scroll. La técnica combina HTML/PHP (para integrar en tu tema), estilos CSS para la apariencia y JavaScript eficiente para añadir/quitar la clase que activa la sombra. Incluyo varias alternativas (scroll event con requestAnimationFrame, IntersectionObserver), cómo cargar los archivos correctamente desde functions.php y consejos de optimización y compatibilidad.

Qué conseguirás

Requisitos previos

1. Estructura HTML / PHP de la cabecera

La mayoría de temas usan header.php para la cabecera. Aquí tienes un fragmento típico. Inserta o adapta según tu tema. La idea es que el elemento principal tenga una clase identificable, por ejemplo .site-header o #site-header.

ltheader id=site-header class=site-headergt
  ltdiv class=site-header-innergt
    lt!-- logo, navegación, botones, etc. --gt
    lta class=site-logo href=lt?php echo esc_url( home_url(/) ) ?gtgtMi weblt/agt
    ltnav class=main-navigationgt
      lt?php wp_nav_menu( array( theme_location =gt primary ) ) ?gt
    lt/navgt
  lt/divgt
lt/headergt

Si tu cabecera ya está en el tema, solo asegúrate de que el elemento raíz tenga un identificador o una clase estable, por ejemplo #site-header o .site-header.

2. CSS base: posición y la sombra activable

Define estilos básicos: posición sticky o fixed, altura, z-index y la transición de la sombra. La clase .has-shadow se añadirá con JavaScript al hacer scroll para activar el box-shadow.

/ Ajusta variables a tu diseño /
:root {
  --header-bg: #ffffff
  --header-height: 72px
  --header-z: 999
  --shadow-color: rgba(0,0,0,0.12)
  --shadow-y: 6px
  --shadow-blur: 18px
  --transition-time: 200ms
}

/ Cabecera fija en top (puedes usar position: sticky si lo prefieres) /
.site-header {
  position: fixed / o sticky /
  top: 0
  left: 0
  right: 0
  height: var(--header-height)
  background: var(--header-bg)
  z-index: var(--header-z)
  transition: box-shadow var(--transition-time) ease, background var(--transition-time) ease
  -webkit-backface-visibility: hidden / suaviza transformaciones /
}

/ Evitar que el contenido suba debajo de la cabecera: añade padding-top al body o al contenedor principal /
body.has-fixed-header .site-content {
  padding-top: var(--header-height)
}

/ Sombra visible sólo cuando se añade la clase /
.site-header.has-shadow {
  box-shadow: 0 var(--shadow-y) var(--shadow-blur) var(--shadow-color)
}

/ Pequeñas mejoras responsive /
@media (max-width: 768px) {
  :root { --header-height: 64px }
}

Notas: si tu tema ya aplica padding-top con un placeholder para cabecera sticky, adapta el selector body.has-fixed-header .site-content o usa otra clase/selector adecuado.

3. JavaScript eficiente para añadir la clase al hacer scroll

Evita listeners costosos en scroll sin moderación. A continuación dos enfoques recomendados:

3.1 Enfoque simple y robusto con requestAnimationFrame (compatible ampliamente)

Este script detecta si la página está en la posición top (offset 0) o está desplazada y añade/quita la clase has-shadow en la cabecera. Usa requestAnimationFrame para limitar repintados.

(function() {
  var header = document.getElementById(site-header)  document.querySelector(.site-header)
  if (!header) return

  var lastY = window.scrollY
  var ticking = false
  var threshold = 4 // px: para evitar micro-fluctuaciones

  function onScroll() {
    lastY = window.scrollY  window.pageYOffset
    if (!ticking) {
      window.requestAnimationFrame(function() {
        updateHeaderShadow(lastY)
        ticking = false
      })
      ticking = true
    }
  }

  function updateHeaderShadow(scrollY) {
    if (scrollY > threshold) {
      if (!header.classList.contains(has-shadow)) header.classList.add(has-shadow)
      document.documentElement.classList.add(has-scrolled) // opcional
    } else {
      header.classList.remove(has-shadow)
      document.documentElement.classList.remove(has-scrolled)
    }
  }

  window.addEventListener(scroll, onScroll, { passive: true })
  // Ejecutar una vez al cargar para estado inicial (por ejemplo reload en medio de la página)
  updateHeaderShadow(window.scrollY  window.pageYOffset)
})()

3.2 Alternativa moderna: IntersectionObserver

En vez de escuchar scroll constantemente, colocas un sentinel justo después del header o al inicio del contenido y observas cuando sale del viewport. Muy eficiente y claro conceptualmente.

(function() {
  var header = document.getElementById(site-header)  document.querySelector(.site-header)
  if (!header) return

  / Inserta en tu template un div sentinel justo después del header:
     ltdiv id=header-sentinel style=position: absolute top: var(--header-height) height: 1px width: 1pxgtlt/divgt
     O crea dinámicamente: /
  var sentinel = document.getElementById(header-sentinel)
  if (!sentinel) {
    sentinel = document.createElement(div)
    sentinel.id = header-sentinel
    sentinel.style.position = absolute
    sentinel.style.top = (header.offsetHeight  0)   px
    sentinel.style.width = 1px
    sentinel.style.height = 1px
    // Añadir al DOM después del header
    header.parentNode.insertBefore(sentinel, header.nextSibling)
  }

  if (IntersectionObserver in window) {
    var io = new IntersectionObserver(function(entries) {
      entries.forEach(function(entry) {
        if (!entry.isIntersecting) {
          header.classList.add(has-shadow)
        } else {
          header.classList.remove(has-shadow)
        }
      })
    }, { root: null, threshold: [0] })

    io.observe(sentinel)
  } else {
    // Fallback al método rAF si no hay IO
    var lastY = window.scrollY
    window.addEventListener(scroll, function() {
      window.requestAnimationFrame(function() {
        if (window.scrollY > 4) header.classList.add(has-shadow)
        else header.classList.remove(has-shadow)
      })
    }, { passive: true })
  }
})()

4. Cómo añadir los scripts y estilos correctamente en functions.php

No pongas JavaScript directamente en header.php sin encolarlo la forma correcta es usar wp_enqueue_script y wp_enqueue_style para evitar conflictos y facilitar cacheo. Añade este código en functions.php de tu tema (idealmente tema hijo).

/ functions.php /
function tema_hijo_enqueue_header_shadow() {
  // CSS (puede estar en tu style.css o archivo separado)
  wp_enqueue_style( tema-header-shadow, get_stylesheet_directory_uri() . /css/header-shadow.css, array(), 1.0 )

  // JS: crea un archivo JS en tu tema hijo, por ejemplo js/header-shadow.js
  wp_enqueue_script( tema-header-shadow-js, get_stylesheet_directory_uri() . /js/header-shadow.js, array(), 1.0, true )

  // Si necesitas pasar datos PHP a JS:
  wp_localize_script( tema-header-shadow-js, HeaderShadowVars, array(
    threshold => 4,
  ) )
}
add_action( wp_enqueue_scripts, tema_hijo_enqueue_header_shadow )

Alternativa: si prefieres inyectar pequeñas porciones de JS inline (no recomendado para grandes scripts), usa wp_add_inline_script sobre un script ya encolado.

5. Manejo del admin bar y otros detalles

6. Personalización de la sombra

Puedes modificar variables CSS para ajustar color, desplazamiento y difuminado. Ejemplos rápidos:

/ Sombra sutil /
--shadow-color: rgba(0,0,0,0.08)
--shadow-y: 4px
--shadow-blur: 10px

/ Sombra pronunciada /
--shadow-color: rgba(0,0,0,0.18)
--shadow-y: 10px
--shadow-blur: 30px

También puedes animar la opacidad para un efecto más suave o añadir una línea inferior en lugar de box-shadow usando ::after y transiciones.

7. Pruebas y depuración

  1. Comprueba la carga del CSS y JS en el inspector de red (DevTools).
  2. Verifica que el selector de la cabecera coincide con el usado en el script (ID o clase).
  3. Recarga la página con cache desactivada o versiona los archivos (cambia el parámetro de versión en wp_enqueue_).
  4. Activa logs JS en consola: console.log dentro del observer o función de rAF para comprobar que se ejecuta.
  5. Prueba en móvil y tablet ajusta threshold y altura de cabecera para evitar saltos no deseados.

8. Posibles errores comunes y soluciones

9. Versión mínima (todo en un snippet) para pruebas rápidas

Si quieres probar rápidamente en un tema de desarrollo, coloca este CSS y JS en los archivos correspondientes. Recuerda mover al functions.php para una integración correcta en producción.

/ quick demo CSS (colocar en header-shadow.css) /
.site-header {
  position: fixed
  top: 0
  left: 0
  right: 0
  height: 64px
  background: #fff
  transition: box-shadow 180ms ease
  z-index: 9999
}
.site-header.has-shadow {
  box-shadow: 0 8px 24px rgba(0,0,0,0.12)
}
body { margin: 0 }
.site-content { padding-top: 64px } / evitar que el contenido quede bajo la cabecera /
/ quick demo JS (colocar en js/header-shadow.js) /
(function() {
  var header = document.querySelector(.site-header)
  if (!header) return
  function update() {
    if (window.pageYOffset > 4) header.classList.add(has-shadow)
    else header.classList.remove(has-shadow)
  }
  window.addEventListener(scroll, update, { passive: true })
  update()
})()

10. Resumen final y recomendaciones

Crear una cabecera con sombra al hacer scroll es una mejora visual sencilla que aporta profundidad y legibilidad. Las mejores prácticas son:

Implementa los fragmentos proporcionados en tu tema hijo, ajusta variables CSS a tu diseño y prueba en distintos dispositivos. Fin del tutorial.



Leave a Reply

Your email address will not be published. Required fields are marked *