Configuración básica y requisitos de scrollspy
Scrollspy es una funcionalidad automática de Bootstrap que resalta dinámicamente los enlaces de navegación basándose en la posición actual de desplazamiento del usuario en la página. Este componente monitoriza constantemente el scroll del navegador y actualiza visualmente los elementos de navegación para mostrar qué sección está siendo visualizada en ese momento.
El comportamiento principal de scrollspy consiste en agregar automáticamente la clase .active
a los enlaces de navegación correspondientes cuando sus secciones objetivo entran en el área visible del viewport. Esto proporciona una retroalimentación visual clara al usuario sobre su ubicación actual dentro del contenido de la página.
Atributos de configuración fundamentales
Para implementar scrollspy necesitas dos atributos esenciales en el elemento contenedor donde se aplicará el seguimiento:
<body data-bs-spy="scroll" data-bs-target="#navbar-principal">
<!-- Contenido de la página -->
</body>
El atributo data-bs-spy="scroll"
activa la funcionalidad de scrollspy en el elemento especificado. Normalmente se aplica al elemento <body>
para monitorizar todo el desplazamiento de la página, aunque también puede aplicarse a contenedores específicos con scroll interno.
El atributo data-bs-target
especifica el selector CSS del elemento de navegación que contiene los enlaces que deben ser resaltados. Este valor debe apuntar exactamente al contenedor de navegación que contiene los enlaces relacionados con las secciones de contenido.
Estructura HTML requerida
Scrollspy requiere una estructura HTML específica para funcionar correctamente. El elemento de navegación debe contener enlaces que apunten a las secciones de contenido mediante anclas:
<!-- Navegación con enlaces de scrollspy -->
<nav id="navbar-principal" class="navbar navbar-expand-lg">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#seccion-inicio">Inicio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#seccion-servicios">Servicios</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#seccion-contacto">Contacto</a>
</li>
</ul>
</nav>
Requisitos de las secciones objetivo
Cada sección de contenido debe tener un ID único que coincida exactamente con el valor href de su enlace correspondiente en la navegación:
<!-- Secciones de contenido con IDs requeridos -->
<div id="seccion-inicio">
<h2>Bienvenidos</h2>
<p>Contenido de la sección de inicio...</p>
</div>
<div id="seccion-servicios">
<h2>Nuestros Servicios</h2>
<p>Descripción de los servicios ofrecidos...</p>
</div>
<div id="seccion-contacto">
<h2>Contacto</h2>
<p>Información de contacto...</p>
</div>
Los IDs deben ser únicos en toda la página y seguir las convenciones de nomenclatura HTML estándar. Bootstrap utiliza estos identificadores para calcular cuándo cada sección entra y sale del viewport visible.
Elemento contenedor scrollable
El elemento que contiene data-bs-spy="scroll"
debe tener la propiedad CSS position: relative
para que scrollspy funcione correctamente. Cuando se aplica al elemento <body>
, esta condición se cumple automáticamente:
<!-- Aplicación típica al body -->
<body data-bs-spy="scroll" data-bs-target="#navegacion-lateral">
<!-- Todo el contenido de la página -->
</body>
Para contenedores específicos con scroll interno, debes asegurar el posicionamiento apropiado:
<!-- Contenedor específico con scroll -->
<div class="container-scroll"
data-bs-spy="scroll"
data-bs-target="#menu-lateral"
style="height: 400px; overflow-y: scroll; position: relative;">
<!-- Contenido con scroll interno -->
</div>
Validación de la configuración
Una configuración básica completa incluye todos los elementos necesarios trabajando en conjunto:
<!DOCTYPE html>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body data-bs-spy="scroll" data-bs-target="#navbar-ejemplo">
<!-- Navegación objetivo -->
<nav id="navbar-ejemplo" class="navbar navbar-expand-lg fixed-top">
<div class="container">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#seccion-1">Sección 1</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#seccion-2">Sección 2</a>
</li>
</ul>
</div>
</nav>
<!-- Contenido con IDs correspondientes -->
<main>
<section id="seccion-1" class="py-5">
<div class="container">
<h2>Primera Sección</h2>
<p>Contenido suficiente para generar scroll...</p>
</div>
</section>
<section id="seccion-2" class="py-5">
<div class="container">
<h2>Segunda Sección</h2>
<p>Más contenido para la segunda sección...</p>
</div>
</section>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Con esta configuración básica, scrollspy funcionará automáticamente sin necesidad de JavaScript adicional, agregando y removiendo la clase .active
en los enlaces de navegación según la posición de scroll del usuario en la página.
Scrollspy con navegación y enlaces
Una vez establecida la configuración básica, scrollspy puede aplicarse a cualquier tipo de navegación de Bootstrap, desde navbars tradicionales hasta navegaciones laterales con tabs y pills. La flexibilidad del componente permite crear experiencias de navegación fluidas en diferentes contextos y diseños.
Aplicación con navbars horizontales
Los navbars horizontales son el caso de uso más común para scrollspy, especialmente en páginas de aterrizaje y documentación. La navegación se mantiene visible mientras el usuario navega por el contenido:
<!-- Navbar horizontal con scrollspy -->
<nav id="navbar-horizontal" class="navbar navbar-expand-lg navbar-dark bg-primary fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Mi Sitio</a>
<div class="navbar-nav">
<a class="nav-link" href="#inicio">Inicio</a>
<a class="nav-link" href="#sobre-nosotros">Sobre Nosotros</a>
<a class="nav-link" href="#servicios">Servicios</a>
<a class="nav-link" href="#portfolio">Portfolio</a>
<a class="nav-link" href="#contacto">Contacto</a>
</div>
</div>
</nav>
<!-- Aplicación en el body -->
<body data-bs-spy="scroll" data-bs-target="#navbar-horizontal">
En este caso, cada enlace del navbar se iluminará automáticamente cuando su sección correspondiente esté visible en el viewport, proporcionando una referencia visual clara de la ubicación actual del usuario.
Navegación lateral con pills
La navegación lateral es especialmente útil para documentación o contenido extenso, donde se necesita un acceso rápido a diferentes secciones desde una posición fija:
<!-- Navegación lateral con pills -->
<div class="row">
<div class="col-md-3">
<nav id="nav-lateral" class="nav nav-pills flex-column sticky-top">
<a class="nav-link" href="#introduccion">Introducción</a>
<a class="nav-link" href="#caracteristicas">Características</a>
<a class="nav-link" href="#instalacion">Instalación</a>
<a class="nav-link" href="#configuracion">Configuración</a>
<a class="nav-link" href="#ejemplos">Ejemplos</a>
</nav>
</div>
<div class="col-md-9" data-bs-spy="scroll" data-bs-target="#nav-lateral">
<!-- Contenido de las secciones -->
<section id="introduccion">
<h2>Introducción</h2>
<p>Contenido de la introducción...</p>
</section>
<!-- Más secciones -->
</div>
</div>
Esta configuración permite que el contenido principal tenga scroll independiente mientras la navegación lateral permanece visible y actualiza automáticamente el estado activo.
Navegación con tabs verticales
Los tabs verticales ofrecen una presentación más estructurada para contenido organizado en secciones claramente diferenciadas:
<!-- Tabs verticales con scrollspy -->
<div class="d-flex">
<nav id="nav-tabs-vertical" class="nav nav-tabs flex-column me-3" style="width: 200px;">
<a class="nav-link" href="#seccion-a">Sección A</a>
<a class="nav-link" href="#seccion-b">Sección B</a>
<a class="nav-link" href="#seccion-c">Sección C</a>
</nav>
<div class="flex-grow-1" data-bs-spy="scroll" data-bs-target="#nav-tabs-vertical" style="height: 500px; overflow-y: auto;">
<div id="seccion-a" class="p-3">
<h3>Contenido de la Sección A</h3>
<p>Información detallada de la primera sección...</p>
</div>
<div id="seccion-b" class="p-3">
<h3>Contenido de la Sección B</h3>
<p>Información detallada de la segunda sección...</p>
</div>
<div id="seccion-c" class="p-3">
<h3>Contenido de la Sección C</h3>
<p>Información detallada de la tercera sección...</p>
</div>
</div>
</div>
Enlaces anidados y navegación multinivel
Scrollspy también funciona con navegaciones más complejas que incluyen enlaces anidados, útil para documentación técnica o contenido con subcategorías:
<!-- Navegación con enlaces anidados -->
<nav id="nav-anidado" class="nav nav-pills flex-column">
<a class="nav-link" href="#capitulo-1">Capítulo 1</a>
<nav class="nav nav-pills flex-column ms-3">
<a class="nav-link" href="#capitulo-1-1">1.1 Introducción</a>
<a class="nav-link" href="#capitulo-1-2">1.2 Conceptos</a>
</nav>
<a class="nav-link" href="#capitulo-2">Capítulo 2</a>
<nav class="nav nav-pills flex-column ms-3">
<a class="nav-link" href="#capitulo-2-1">2.1 Implementación</a>
<a class="nav-link" href="#capitulo-2-2">2.2 Ejemplos</a>
</nav>
</nav>
En estructuras anidadas, tanto los enlaces principales como los sub-enlaces reciben la clase .active
cuando corresponde, creando una jerarquía visual clara de la navegación.
Integración con list groups
Los list groups proporcionan una alternativa estilística para la navegación lateral, especialmente útil en dashboards o paneles de administración:
<!-- List group como navegación -->
<div class="row">
<div class="col-md-4">
<div id="list-navegacion" class="list-group sticky-top">
<a class="list-group-item list-group-item-action" href="#configuracion-general">
Configuración General
</a>
<a class="list-group-item list-group-item-action" href="#configuracion-usuario">
Configuración de Usuario
</a>
<a class="list-group-item list-group-item-action" href="#configuracion-seguridad">
Configuración de Seguridad
</a>
<a class="list-group-item list-group-item-action" href="#configuracion-notificaciones">
Notificaciones
</a>
</div>
</div>
<div class="col-md-8" data-bs-spy="scroll" data-bs-target="#list-navegacion">
<!-- Secciones de configuración -->
</div>
</div>
Ejemplo práctico: página de portfolio
Un caso de uso completo muestra cómo scrollspy mejora la experiencia de navegación en una página de portfolio profesional:
<!-- Navbar principal del portfolio -->
<nav id="portfolio-nav" class="navbar navbar-expand-lg navbar-light bg-white fixed-top shadow-sm">
<div class="container">
<a class="navbar-brand fw-bold" href="#">Juan Pérez</a>
<div class="navbar-nav ms-auto">
<a class="nav-link" href="#hero">Inicio</a>
<a class="nav-link" href="#about">Acerca de</a>
<a class="nav-link" href="#projects">Proyectos</a>
<a class="nav-link" href="#skills">Habilidades</a>
<a class="nav-link" href="#contact">Contacto</a>
</div>
</div>
</nav>
<!-- Aplicación del scrollspy -->
<body data-bs-spy="scroll" data-bs-target="#portfolio-nav">
<section id="hero" class="vh-100 d-flex align-items-center bg-primary text-white">
<div class="container text-center">
<h1>Desarrollador Frontend</h1>
<p class="lead">Creando experiencias web excepcionales</p>
</div>
</section>
<section id="about" class="py-5">
<div class="container">
<h2>Acerca de Mí</h2>
<p>Información profesional y experiencia...</p>
</div>
</section>
<!-- Más secciones del portfolio -->
</body>
En este ejemplo, la navegación se mantiene fija en la parte superior y cada enlace se resalta automáticamente cuando el usuario navega por las diferentes secciones del portfolio, creando una experiencia fluida y profesional.
Estados visuales automáticos
Cuando scrollspy está activo, Bootstrap maneja automáticamente la aplicación de la clase .active
a los elementos de navegación correspondientes. Esto significa que los estilos visuales de los componentes nav, navbar, list-group y pills se actualizan sin intervención manual, manteniendo la consistencia visual que caracteriza al framework.
La actualización automática del estado activo funciona de manera inteligente, removiendo la clase .active
del enlace anterior antes de aplicarla al nuevo enlace correspondiente, asegurando que solo un elemento esté marcado como activo en cualquier momento dado.
Personalización de offset y comportamiento
El comportamiento predeterminado de scrollspy puede personalizarse mediante varios atributos de datos para adaptarse a diferentes necesidades de diseño y experiencia de usuario. La personalización más común y útil es el ajuste del offset, que permite controlar cuándo exactamente se activa el resaltado de los enlaces de navegación.
Configuración del offset básico
El atributo data-bs-offset
define la distancia en píxeles desde la parte superior del viewport que scrollspy utiliza para determinar cuándo una sección está "activa". Esta configuración es esencial cuando se trabaja con navegaciones fijas que pueden ocultar parte del contenido:
<!-- Scrollspy con offset personalizado -->
<body data-bs-spy="scroll"
data-bs-target="#navbar-fijo"
data-bs-offset="80">
<!-- Navbar fijo que ocupa 60px de altura -->
<nav id="navbar-fijo" class="navbar navbar-expand-lg fixed-top bg-white shadow" style="height: 60px;">
<div class="container">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#seccion-hero">Inicio</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#seccion-servicios">Servicios</a>
</li>
</ul>
</div>
</nav>
</body>
En este ejemplo, el offset de 80px asegura que la sección se considere activa cuando su parte superior está 80 píxeles por debajo del borde superior del viewport, compensando así la altura del navbar fijo y proporcionando un margen adicional.
Cálculo del offset apropiado
Para determinar el valor correcto del offset, debes considerar todos los elementos fijos que pueden interferir con la visualización del contenido:
<!-- Navbar con múltiples elementos fijos -->
<header class="fixed-top">
<!-- Barra de anuncio: 40px -->
<div class="bg-primary text-white text-center py-2">
<small>Oferta especial - 50% de descuento</small>
</div>
<!-- Navbar principal: 60px -->
<nav id="nav-principal" class="navbar navbar-expand-lg bg-white border-bottom">
<div class="container">
<div class="navbar-nav">
<a class="nav-link" href="#productos">Productos</a>
<a class="nav-link" href="#testimonios">Testimonios</a>
<a class="nav-link" href="#contacto">Contacto</a>
</div>
</div>
</nav>
</header>
<!-- Offset calculado: 40px + 60px + 20px margen = 120px -->
<body data-bs-spy="scroll"
data-bs-target="#nav-principal"
data-bs-offset="120">
Configuración de smooth scroll
El atributo data-bs-smooth-scroll
activa el desplazamiento suave cuando se hace clic en los enlaces de navegación, mejorando la experiencia visual del usuario:
<!-- Scrollspy con desplazamiento suave -->
<body data-bs-spy="scroll"
data-bs-target="#navegacion-lateral"
data-bs-offset="100"
data-bs-smooth-scroll="true">
<div class="row">
<div class="col-md-3">
<nav id="navegacion-lateral" class="nav nav-pills flex-column sticky-top">
<a class="nav-link" href="#capitulo-1">Capítulo 1</a>
<a class="nav-link" href="#capitulo-2">Capítulo 2</a>
<a class="nav-link" href="#capitulo-3">Capítulo 3</a>
</nav>
</div>
<div class="col-md-9">
<section id="capitulo-1" class="mb-5">
<h2>Primer Capítulo</h2>
<p>Contenido extenso del primer capítulo...</p>
</section>
</div>
</div>
</body>
Personalización en contenedores específicos
Cuando scrollspy se aplica a contenedores específicos en lugar del body completo, el offset se comporta de manera relativa al contenedor:
<!-- Contenedor con scroll personalizado -->
<div class="card">
<div class="card-header">
<nav id="nav-contenido" class="nav nav-tabs card-header-tabs">
<a class="nav-link" href="#introduccion">Introducción</a>
<a class="nav-link" href="#desarrollo">Desarrollo</a>
<a class="nav-link" href="#conclusion">Conclusión</a>
</nav>
</div>
<div class="card-body overflow-auto"
style="height: 400px;"
data-bs-spy="scroll"
data-bs-target="#nav-contenido"
data-bs-offset="50">
<section id="introduccion" class="mb-4">
<h3>Introducción</h3>
<p>Texto de la introducción...</p>
</section>
<section id="desarrollo" class="mb-4">
<h3>Desarrollo del Tema</h3>
<p>Contenido principal del desarrollo...</p>
</section>
<section id="conclusion" class="mb-4">
<h3>Conclusiones</h3>
<p>Reflexiones finales sobre el tema...</p>
</section>
</div>
</div>
Configuración de método de activación
El atributo data-bs-method
permite especificar el método utilizado para determinar qué enlaces deben activarse. Los valores disponibles son auto
, offset
, y position
:
<!-- Método de activación personalizado -->
<body data-bs-spy="scroll"
data-bs-target="#menu-principal"
data-bs-offset="70"
data-bs-method="position">
<!-- La navegación funcionará basada en posición exacta -->
<nav id="menu-principal" class="navbar fixed-top">
<div class="container">
<a class="nav-link" href="#seccion-1">Sección 1</a>
<a class="nav-link" href="#seccion-2">Sección 2</a>
</div>
</nav>
</body>
Ejemplo práctico: documentación técnica
Un caso completo de personalización muestra cómo combinar diferentes opciones para crear una experiencia de navegación óptima en documentación:
<!-- Documentación con scrollspy personalizado -->
<div class="container-fluid">
<div class="row">
<!-- Sidebar de navegación -->
<nav id="sidebar-docs" class="col-md-3 col-lg-2 d-md-block bg-light sidebar">
<div class="position-sticky pt-3">
<div class="nav flex-column">
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted">
Primeros Pasos
</h6>
<a class="nav-link" href="#instalacion">Instalación</a>
<a class="nav-link" href="#configuracion">Configuración</a>
<h6 class="sidebar-heading px-3 mt-4 mb-1 text-muted">
Componentes
</h6>
<a class="nav-link" href="#botones">Botones</a>
<a class="nav-link" href="#formularios">Formularios</a>
<a class="nav-link" href="#navegacion">Navegación</a>
</div>
</div>
</nav>
<!-- Contenido principal -->
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4"
data-bs-spy="scroll"
data-bs-target="#sidebar-docs"
data-bs-offset="120"
data-bs-smooth-scroll="true"
data-bs-method="offset">
<section id="instalacion" class="py-4">
<h1>Instalación</h1>
<p>Guía completa de instalación del framework...</p>
<!-- Contenido extenso -->
</section>
<section id="configuracion" class="py-4">
<h1>Configuración Inicial</h1>
<p>Pasos para configurar correctamente el entorno...</p>
</section>
<section id="botones" class="py-4">
<h1>Componente Botones</h1>
<p>Documentación completa sobre el uso de botones...</p>
</section>
</main>
</div>
</div>
Configuración responsive del offset
Para diferentes tamaños de pantalla, puedes necesitar ajustar el offset dinámicamente usando CSS custom properties y media queries:
<style>
:root {
--scrollspy-offset: 80px;
}
@media (max-width: 768px) {
:root {
--scrollspy-offset: 60px;
}
}
</style>
<!-- Aplicación con CSS personalizado para offset responsive -->
<body data-bs-spy="scroll"
data-bs-target="#nav-responsive"
data-bs-offset="80">
<nav id="nav-responsive" class="navbar fixed-top">
<!-- Navbar que cambia de altura según el dispositivo -->
<div class="container">
<a class="nav-link" href="#mobile-first">Mobile First</a>
<a class="nav-link" href="#responsive-design">Responsive Design</a>
</div>
</nav>
</body>
Optimización del comportamiento
La combinación adecuada de configuraciones permite crear experiencias de navegación fluidas y precisas:
<!-- Configuración optimizada para landing page -->
<body data-bs-spy="scroll"
data-bs-target="#landing-nav"
data-bs-offset="100"
data-bs-smooth-scroll="true"
data-bs-method="offset">
<nav id="landing-nav" class="navbar navbar-expand-lg fixed-top bg-white shadow-sm">
<div class="container">
<div class="navbar-nav mx-auto">
<a class="nav-link px-3" href="#hero">Inicio</a>
<a class="nav-link px-3" href="#features">Características</a>
<a class="nav-link px-3" href="#pricing">Precios</a>
<a class="nav-link px-3" href="#testimonials">Testimonios</a>
<a class="nav-link px-3" href="#contact">Contacto</a>
</div>
</div>
</nav>
</body>
Estas configuraciones de personalización permiten que scrollspy se adapte perfectamente a cualquier diseño, proporcionando una experiencia de navegación fluida y precisa sin necesidad de JavaScript personalizado adicional.
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en Bootstrap
Documentación oficial de Bootstrap
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Bootstrap es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Bootstrap
Explora más contenido relacionado con Bootstrap y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
- Comprender el funcionamiento básico de Scrollspy y sus atributos esenciales.
- Aprender la estructura HTML requerida para implementar Scrollspy correctamente.
- Conocer cómo aplicar Scrollspy en diferentes tipos de navegación: navbars, navegación lateral, tabs y list groups.
- Configurar y personalizar el offset y el comportamiento del Scrollspy para adaptarlo a distintos diseños.
- Implementar desplazamiento suave y métodos de activación personalizados para mejorar la experiencia de usuario.