Tutorial WordPress: Crear un layout de documentación por secciones con navegación sticky

·

·

Introducción

Este tutorial explica paso a paso cómo crear en WordPress un layout para documentación por secciones con una navegación sticky (fija) lateral o superior. Cubriremos varias estrategias (ACF/repeater, parseo de encabezados en el contenido, y menú de anclas), el HTML/PHP necesario, el CSS para el layout y el comportamiento sticky, y el JavaScript para resaltar la sección activa (scrollspy) y navegación suave. También incluimos buenas prácticas de accesibilidad, rendimiento y responsive design.

Requisitos previos

Decidir la estrategia

Tres enfoques habituales, con sus pros y contras:

  1. ACF / Repeater: Control total sobre títulos y contenido de cada sección. Ideal si quieres estructura rígida y editor amigable.
  2. Parsear encabezados del contenido: Fácil de usar con el editor Gutenberg: el autor escribe H2/H3 en la página y el sistema genera la navegación automáticamente. Menos control fino pero muy cómodo.
  3. Menú de anclas manual: Creas un menú (wp_nav_menu) con enlaces a anclas. Útil si quieres que la navegación sea editabledesde Apariencia → Menús.

Recomendación

Si publicas documentación frecuente y quieres editar secciones como elementos separados, usar ACF Repeater o un Custom Post Type con relaciones es lo más escalable. Si prefieres simplicidad y que el autor use el editor, parsear encabezados es rápido y robusto.

Plantilla básica (estructura HTML/PHP)

Ejemplo de plantilla de página que genera una navegación lateral y un área de contenido con secciones. Aquí mostramos la variante con ACF Repeater (título y contenido por sección).

lt?php
/
  Template Name: Documentación con navegación sticky
 /
get_header()
?gt

ltmain class=doc-layoutgt
  ltnav class=doc-nav aria-label=Índice de la documentacióngt
    ltul class=doc-nav-listgt
      lt?php if( have_rows(secciones) ): i=0
        while( have_rows(secciones) ): the_row() i  
          titulo = get_sub_field(titulo)
          slug = sanitize_title(titulo) . - . i
      ?gt
        ltligtlta href=#lt?php echo esc_attr(slug) ?gtgtlt?php echo esc_html(titulo) ?gtlt/agtlt/ligt
      lt?php endwhile endif ?gt
    lt/ulgt
  lt/navgt

  ltsection class=doc-contentgt
    lt?php if( have_rows(secciones) ): i=0
      while( have_rows(secciones) ): the_row() i  
        titulo = get_sub_field(titulo)
        contenido = get_sub_field(contenido)
        slug = sanitize_title(titulo) . - . i
    ?gt
      ltarticle id=lt?php echo esc_attr(slug) ?gt class=doc-section tabindex=-1gt
        lth2gtlt?php echo esc_html(titulo) ?gtlt/h2gt
        ltdiv class=doc-section-bodygtlt?php echo wp_kses_post(contenido) ?gtlt/divgt
      lt/articlegt
    lt?php endwhile endif ?gt
  lt/sectiongt
lt/maingt

lt?php get_footer() ?gt

Notas sobre la plantilla

Opción alternativa: parsear H2 del contenido

Si prefieres que el editor solo use encabezados H2/H3 y el sistema genere el índice automáticamente, aquí tienes una función que extrae H2 y genera el índice.

function doc_extract_headings( content ) {
  headings = array()
  if ( preg_match_all( /lth2.?gt(.?)lt/h2gt/i, content, matches ) ) {
    i = 0
    foreach ( matches[1] as text ) {
      i  
      plain = wp_strip_all_tags( text )
      slug = sanitize_title( plain ) . - . i
      headings[] = array( text =gt plain, id =gt slug )
      // Replace the H2 in content with an id for linking
      content = preg_replace( /lth2(.?)gt.preg_quote(text).lt/h2gt/i,
        lth2 id=.esc_attr(slug).1gt.text.lt/h2gt, content, 1 )
    }
  }
  return array( content =gt content, headings =gt headings )
}

En el template cargarías post_content, pasarías por doc_extract_headings(), imprimirías la navegación usando el array headings y finalmente el contenido modificado.

CSS para layout y navegación sticky

A continuación un CSS base para un layout de dos columnas con navegación sticky en el lateral. Ajusta colores y tamaños a tu tema.

/ Contenedor principal /
.doc-layout{
  display: grid
  grid-template-columns: 300px 1fr
  gap: 32px
  align-items: start
  padding: 24px
}

/ Navegación lateral /
.doc-nav{
  position: relative
}
.doc-nav-list{
  list-style: none
  margin: 0
  padding: 0
  max-height: calc(100vh - 48px) / dejar espacio para encabezado fijo /
  overflow: auto
  position: sticky
  top: 24px
  border-left: 3px solid transparent
}

/ Enlaces /
.doc-nav-list a{
  display: block
  padding: 8px 12px
  color: #1a1a1a
  text-decoration: none
}
.doc-nav-list a:hover,
.doc-nav-list a:focus{
  background: rgba(0,0,0,0.04)
  outline: none
}

/ Enlace activo (sección visible) /
.doc-nav-list a.is-active{
  font-weight: 700
  color: #0066cc
  border-left: 3px solid #0066cc
  padding-left: 9px / compensar borde /
}

/ Contenido principal /
.doc-content{
  min-width: 0
}
.doc-section{
  margin-bottom: 48px
  scroll-margin-top: 96px / compensar encabezado fijo si existe /
}

/ Responsive: en pantallas pequeñas la nav va arriba /
@media (max-width: 880px){
  .doc-layout{
    grid-template-columns: 1fr
  }
  .doc-nav{
    order: -1
    margin-bottom: 16px
  }
  .doc-nav-list{
    position: static
    max-height: none
  }
}

JavaScript: scrollspy con IntersectionObserver y smooth scrolling

Este script detecta qué sección está visible y añade la clase is-active al enlace correspondiente. Usa IntersectionObserver para eficiencia y navegación suave al hacer clic en enlaces de la navegación.

document.addEventListener(DOMContentLoaded, function(){
  const navLinks = document.querySelectorAll(.doc-nav-list a)
  const sections = Array.from(navLinks).map(link =gt {
    const id = link.getAttribute(href).replace(#,)
    return document.getElementById(id)
  }).filter(Boolean)

  // Smooth scroll for nav links
  navLinks.forEach(link =gt {
    link.addEventListener(click, function(e){
      e.preventDefault()
      const targetId = this.getAttribute(href).slice(1)
      const target = document.getElementById(targetId)
      if(target){
        target.focus({preventScroll: true})
        window.scrollTo({
          top: target.getBoundingClientRect().top   window.scrollY - 80, // ajustar offset si cabezal fijo
          behavior: smooth
        })
        // update URL without jumping
        history.replaceState(null, , # targetId)
      }
    })
  })

  // IntersectionObserver para marcar el enlace activo
  const observer = new IntersectionObserver((entries) =gt {
    entries.forEach(entry =gt {
      const id = entry.target.id
      const link = document.querySelector(.doc-nav-list a[href=# id ])
      if(entry.isIntersecting){
        navLinks.forEach(l =gt l.classList.remove(is-active))
        if(link) link.classList.add(is-active)
      }
    })
  }, { root: null, rootMargin: -40% 0px -40% 0px, threshold: 0 })

  sections.forEach(sec =gt observer.observe(sec))

  // Fallback: en navegadores muy antiguos, podrías añadir un scroll listener si IntersectionObserver no existe.
})

Notas sobre el script

Encolar scripts y estilos en functions.php

Ejemplo de cómo añadir los assets al tema correctamente.

function doc_enqueue_assets(){
  wp_enqueue_style( doc-layout, get_stylesheet_directory_uri() . /css/doc-layout.css, array(), 1.0 )
  wp_enqueue_script( doc-scrollspy, get_stylesheet_directory_uri() . /js/doc-scrollspy.js, array(), 1.0, true )
}
add_action( wp_enqueue_scripts, doc_enqueue_assets )

Accesibilidad (a11y) y UX

Responsive y dispositivos móviles

En pantallas pequeñas es mejor mover la navegación arriba del contenido o convertirla en un panel colapsable (accordion/drawer). Evita position: sticky con top grande que provoque que el nav quede fuera de la pantalla en móviles.

Optimización y rendimiento

Pruebas y depuración

Ejemplo completo mínimo (resumen)

Resumen rápido de los pasos para implementar en un sitio:

  1. Crear un template de página o página específica.
  2. Elegir cómo generar las secciones (ACF, parseo de H2 o menú manual).
  3. Generar IDs únicos para cada sección y enlaces que apunten a esas IDs.
  4. Estilizar el layout con CSS, usando position: sticky en la navegación.
  5. Añadir JS con IntersectionObserver para scrollspy y smooth scroll.
  6. Encolar assets correctamente y probar accesibilidad y responsive.

Consejos finales

Ejemplo ACF: estructura de campos recomendada

Si usas ACF, crea un campo repeater llamado secciones con subcampos:

Checklist antes de publicar

Conclusión

Crear un layout de documentación por secciones con navegación sticky en WordPress es una mejora de usabilidad potente y relativamente sencilla si se planifica bien. Elige la estrategia que encaje con tu flujo editorial (ACF para control, parseo de H2 para agilidad, menú manual para edición directa por administradores) y aplica los patrones mostrados: IDs únicos, position: sticky, IntersectionObserver para scrollspy y buenas prácticas de accesibilidad. Con esto tendrás una documentación clara, navegable y profesional lista para publicar.



Leave a Reply

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