Cómo resolver el problema de los enlaces de anclaje ocultados por la barra de navegación sticky con solo unas líneas de CSS en línea
Cuando haces clic en un enlace de pie de página o en el índice (TOC) de un documento (blog, wiki, guía), el navegador se desplaza a #some-id y alinea el elemento con ese id justo en la parte superior del viewport.
Si en la parte superior tienes una barra de navegación con position: sticky (o fixed), el desplazamiento se alinea con la parte superior, pero el contenido queda oculto detrás de la barra.
Este es un problema frecuente en el frontend, pero para desarrolladores backend o full‑stack puede resultar desconcertante: “el enlace funciona, pero el contenido no se muestra”.
En este artículo describo la técnica que uso con más frecuencia: añadir unas pocas líneas de CSS en línea en la página problemática (la forma más simple y efectiva).
¿Por qué ocurre esto?
El comportamiento por defecto del navegador es el siguiente:
- Cuando la URL cambia a
.../page#target - El navegador busca el elemento con
id="target" - Desplaza la página de modo que el inicio de ese elemento quede en la parte superior del contenedor de desplazamiento (normalmente el viewport).
Pero la barra sticky se renderiza sobre el viewport, por lo que el elemento queda oculto debajo de la barra.

La solución más sencilla: scroll-margin-top (añade margen al elemento)
Si le das scroll-margin-top al elemento que se mostrará al hacer clic, el navegador intentará posicionarlo un poco más abajo que la parte superior.
Aplicación mínima con CSS en línea (recomendado)
En la página con el problema, basta con añadir lo siguiente en el <head> o en la plantilla de la página:
<style>
:root { --sticky-nav-h: 64px; } /* ajusta a la altura real de la barra */
[id] { scroll-margin-top: calc(var(--sticky-nav-h) + 12px); }
</style>
--sticky-nav-h: altura de la barra sticky.+ 12px: margen extra para evitar que quede justo debajo de la barra (puedes ajustarlo).
Si aplicas
[id]globalmente, todos los enlaces de anclaje de la página se ajustarán automáticamente. Si prefieres limitar el alcance, puedes restringirlo a un contenedor.
Limitar el alcance para mayor seguridad
Ejemplo: solo en el contenido principal
<style>
:root { --sticky-nav-h: 64px; }
.article [id] { scroll-margin-top: calc(var(--sticky-nav-h) + 12px); }
</style>
Ejemplo: si el TOC enlaza mayormente a h2/h3
<style>
:root { --sticky-nav-h: 64px; }
.article h2[id], .article h3[id] {
scroll-margin-top: calc(var(--sticky-nav-h) + 12px);
}
</style>
Opción complementaria: scroll-padding-top (paddings del contenedor)
scroll-padding-top indica al contenedor de desplazamiento que reserve un área segura en la parte superior. En la práctica, scroll-margin-top suele ser más intuitivo, pero combinarlos puede mejorar la estabilidad según el diseño.
<style>
:root { --sticky-nav-h: 64px; }
html { scroll-padding-top: calc(var(--sticky-nav-h) + 12px); }
</style>
- Útil cuando quieres corregir todos los enlaces de anclaje de la página de forma rápida.
- Si necesitas controlar solo ciertos elementos,
scroll-margin-topsigue siendo la mejor opción.
Truco clásico para compatibilidad: usar ::before para crear un offset falso
Esta técnica ha existido desde hace tiempo. Se inserta un bloque invisible antes del elemento objetivo, de modo que su posición real se desplaza debajo de la barra.
<style>
:root { --sticky-nav-h: 64px; }
.anchor-target::before {
content: "";
display: block;
height: calc(var(--sticky-nav-h) + 12px);
margin-top: calc(-1 * (var(--sticky-nav-h) + 12px));
visibility: hidden;
pointer-events: none;
}
</style>
Ejemplo de uso:
<h2 id="install" class="anchor-target">Instalación</h2>
- Ventaja: funciona en navegadores muy antiguos.
- Desventaja: requiere añadir una clase y ajustar la selección de elementos.
Hoy en día, se recomienda probar primero con scroll-margin-top y, si algo falla, recurrir al truco con ::before.
Solución con JavaScript: ¿cuándo es mejor usar CSS?
Es posible usar scrollIntoView() y luego window.scrollBy(0, -navHeight) para corregir la posición. Sin embargo, el CSS suele ser la opción preferida porque:
- No necesita dependencias ni scripts adicionales.
- Es más fácil de depurar y revertir.
- Se adapta bien a páginas estáticas con mucho contenido (p. ej., documentación, TOC, notas al pie).
Recomendaciones:
- Páginas de contenido estático con muchos enlaces de anclaje.
- Cuando no quieres tocar la lógica de enrutamiento o el framework.
- Cuando el mantenedor puede no ser un experto en frontend.
Checklist de producción
- Determina la altura exacta de la barra sticky.
- Si la altura cambia con los breakpoints, actualiza
--sticky-nav-hen cada breakpoint. - No amplíes demasiado el alcance de la regla.
[id]global es cómodo, pero.article [id]suele ser suficiente.- Añade un margen extra de 8‑16 px para mejorar la percepción visual.
Conclusión: mi solución favorita
Para la mayoría de los casos, basta con añadir lo siguiente en línea en la página problemática:
<style>
:root { --sticky-nav-h: 64px; }
.article [id] { scroll-margin-top: calc(var(--sticky-nav-h) + 12px); }
</style>
Con esto, el TOC, las notas al pie y los enlaces profundos se resuelven de una sola vez. Espero que este enfoque sea útil para los desarrolladores que enfrentan el problema de los enlaces ocultos por la barra sticky.
Artículos relacionados
- Razones y beneficios de especificar width y height en la etiqueta de imagen
- Incluso un ingeniero backend debe conocer al menos esto - Los 5 mejores métodos de JS y módulos frontend
No hay comentarios.