Tutorial WordPress: Crear una cabecera “pegada” que oculta/mostrar sombra según scroll (CSS)

·

·

Introducción

En este tutorial detallado vas a aprender a crear una cabecera “pegada” (sticky/fixed) en WordPress que muestra u oculta una sombra cuando el usuario hace scroll. La idea es mantener la cabecera visible y limpia cuando la página está en la parte superior y añadir una sombra sutil cuando el usuario se desplaza, para que la cabecera se perciba por encima del contenido. El resultado combina CSS para el estilo y una pequeña porción de JavaScript para detectar el scroll (método recomendado por compatibilidad). También incluyo una alternativa CSS pura usando CSS :has() (experimental y con soporte limitado).

Resumen de la solución

HTML (estructura recomendada)

Coloca este HTML en tu plantilla de cabecera (por ejemplo header.php) o adapta las clases si tu tema ya tiene sus propias clases. El ejemplo es genérico y claro para entender dónde actúa el CSS/JS.

ltheader class=site-header role=bannergt
  ltdiv class=wrapgt
    lta class=site-logo href=/ title=IniciogtMi sitiolt/agt
    ltnav class=site-nav role=navigationgt
      ltulgt
        ltligtlta href=/sobregtSobrelt/agtlt/ligt
        ltligtlta href=/contactogtContactolt/agtlt/ligt
      lt/ulgt
    lt/navgt
  lt/divgt
lt/headergt

CSS (estilos principales)

Este CSS fija la cabecera, aplica una transición suave y define la sombra que aparecerá cuando la cabecera tenga la clase .is-scrolled. Ajusta variables (colores, alturas) a tu tema.

:root{
  --header-height: 68px / Ajustar a la altura real de la cabecera /
  --header-bg: rgba(255,255,255,0.98)
  --header-z: 1000
  --shadow-color: rgba(0,0,0,0.12)
}

/ Reset básico (opcional) /
.site-header{
  box-sizing: border-box
}

/ Cabecera pegada /
.site-header{
  position: fixed
  top: 0
  left: 0
  right: 0
  height: var(--header-height)
  background: var(--header-bg)
  z-index: var(--header-z)
  display: flex
  align-items: center
  transition: box-shadow 220ms ease, background-color 220ms ease, transform 200ms ease
  box-shadow: none / sin sombra en el tope /
  -webkit-backdrop-filter: saturate(110%) blur(4px) / opcional, solo en navegadores compatibles /
  backdrop-filter: saturate(110%) blur(4px)
}

/ Para que el contenido no quede debajo de la cabecera (evitar salto) /
html {
  / Si tu tema añade padding o margin al body, mejor añadir el margen en el main container.
     Aquí se muestra el concepto: puedes añadir padding-top al .site-content en lugar de html/body. /
}
body {
  padding-top: var(--header-height)
}

/ Sombra que aparece al hacer scroll (clase activada por JS) /
.site-header.is-scrolled{
  box-shadow: 0 6px 18px -8px var(--shadow-color)
  background: rgba(255,255,255,0.96)
}

/ Variante: sombra más sutil cuando no hay fondo blanco /
.site-header.transparent{
  background: transparent
}

/ Ajustes responsivos: ejemplo /
@media (max-width: 768px){
  :root{ --header-height: 56px }
  .site-header{ height: var(--header-height) }
}

Notas CSS importantes

  1. Asegúrate de que la variable –header-height refleje la altura real de la cabecera. Si tu cabecera tiene altura dinámica, usa un valor fijo o calcula el padding-top con JS al cargar.
  2. Evita usar top: 0 en combinación con transform translateY para animaciones, salvo que quieras animar la cabecera fuera de la pantalla.
  3. La propiedad backdrop-filter mejora apariencia en cabeceras semitransparentes pero no es soportada en todos los navegadores—no depende de la funcionalidad de la sombra.

JavaScript (detectar scroll y alternar clase)

Un script ligero que comprueba si el usuario ha hecho scroll hacia abajo y, si es así, añade la clase .is-scrolled a la cabecera. Lleva una pequeña mejora de rendimiento usando requestAnimationFrame para evitar recálculos excesivos en scroll rápido.

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

  var lastKnownScrollY = 0
  var ticking = false
  var threshold = 6 // píxeles mínimos para activar (evita parpadeos en micro-scrolls)

  function onScroll() {
    lastKnownScrollY = window.scrollY  window.pageYOffset
    requestTick()
  }

  function requestTick() {
    if(!ticking) {
      requestAnimationFrame(update)
    }
    ticking = true
  }

  function update() {
    ticking = false
    var y = lastKnownScrollY
    if(y > threshold){
      if(!header.classList.contains(is-scrolled)){
        header.classList.add(is-scrolled)
      }
    } else {
      if(header.classList.contains(is-scrolled)){
        header.classList.remove(is-scrolled)
      }
    }
  }

  window.addEventListener(scroll, onScroll, {passive:true})
  // Ejecutar una vez al cargar para cubrir el caso de reload en mitad de página
  update()
})()

Mejoras opcionales al JS

Alternativa: CSS puro con :has() (experimental)

Si prefieres no usar JavaScript, existe una técnica que coloca un sentinel (un elemento vacío justo después del header) y usa :has() y :not() para detectar si el sentinel está intersectando. Esto funciona sólo en navegadores que soportan :has() y comportamientos específicos comprobar compatibilidad antes de usar en producción.

/ Estructura requerida:
   ltheader class=site-headergt...lt/headergt
   ltdiv class=header-sentinelgtlt/divgt
   .header-sentinel debe estar pegado justo después del header en el DOM.
/

.header-sentinel{
  height: 1px
  margin-top: calc(-1px) / pegado visualmente al final del header /
}

/ Si el header no toca el tope (es decir, el sentinel ha salido del view), se aplica la sombra /
.site-header:has(  .header-sentinel:not(:root:where(:root))){
  / Esta regla es conceptual. La especificidad y el selector exacto
     pueden variar y su compatibilidad es limitada. /
  box-shadow: 0 6px 18px -8px rgba(0,0,0,0.12)
}

Importante: :has() todavía no está soportado en todos los navegadores (ver soporte actual). Por compatibilidad, la solución con JavaScript es la más robusta.

Integración en WordPress (enqueue de estilos y scripts)

Para añadir el CSS y JS correctamente en WordPress sin editar archivos directamente del núcleo, usa functions.php de tu tema (o mejor, un plugin de funcionalidad). Ejemplo de cómo encolar los archivos:

function mi_tema_enqueue_sticky_header(){
  // CSS principal del tema (ya suele estar encolado). Aquí se añade un archivo adicional si hace falta.
  wp_enqueue_style(
    mi-sticky-header-css,
    get_stylesheet_directory_uri() . /assets/css/sticky-header.css,
    array(),
    1.0
  )

  // JS ligero para alternar la clase.
  wp_enqueue_script(
    mi-sticky-header-js,
    get_stylesheet_directory_uri() . /assets/js/sticky-header.js,
    array(),
    1.0,
    true
  )
}
add_action(wp_enqueue_scripts, mi_tema_enqueue_sticky_header)

Coloca el CSS del ejemplo en assets/css/sticky-header.css y el JS en assets/js/sticky-header.js (o integra en tus archivos existentes). Al usar el último parámetro en wp_enqueue_script como true, el script se carga en el footer para no bloquear el render inicial.

Optimización y buenas prácticas

  1. Usa passive: true en addEventListener(scroll) para mejorar la respuesta del scroll en móviles.
  2. Reduce el trabajo en cada evento de scroll el ejemplo usa requestAnimationFrame para agrupar actualizaciones y evitar layout thrashing.
  3. Evita reflow costoso dentro del handler (por ejemplo, no leer y escribir propiedades que fuerzan layout repetidamente).
  4. Si tu tema usa un constructor o framework, adapta las clases y la integración para respetar su estructura (ej.: Elementor, Divi, etc.).
  5. Prueba en dispositivos móviles y navegadores donde la barra de dirección puede cambiar el viewport height (scrollY puede fluctuar) la lógica con umbral evita parpadeos.

Accesibilidad y UX

Recapitulación final

Resumen rápido de pasos para implementar la cabecera pegada con sombra condicional:

  1. Marcar la cabecera con una clase clara (.site-header) y asegurarte de que el HTML del tema lo use.
  2. Aplicar CSS para fijar la cabecera, definir la transición y la sombra cuando esté la clase .is-scrolled.
  3. Agregar un pequeño script que detecte el scroll y añada/quite la clase .is-scrolled usando requestAnimationFrame para eficiencia.
  4. Encolar correctamente los archivos CSS/JS en WordPress mediante functions.php.

Ejemplo completo — ubicación sugerida de archivos

Observación final

La combinación CSS un JS mínimo ofrece la mayor compatibilidad y control. Si necesitas que el comportamiento sea completamente sin JS, revisa el método con :has() pero ten en cuenta las limitaciones de soporte. Ajusta las variables CSS y la lógica de umbral para adaptarlo a tu diseño y experiencia deseada.



Leave a Reply

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