CSS / HTML / Avanzado / 3 min
Barra de progreso de scroll en CSS
Indicador de lectura con CSS animation-timeline y fallback JavaScript para navegadores sin soporte.
Esta barra muestra cuánto avanzó el usuario en la lectura de una página.
El método principal usa CSS Scroll-Driven Animations con animation-timeline. Para Safari y navegadores sin soporte, el snippet incluye un fallback JavaScript con requestAnimationFrame.
Guía de Implementación Paso a Paso
- Pega el HTML al inicio de
<body>. - Añade el CSS en tu hoja global o dentro del
<head>. - Personaliza
--progress-colory--progress-height. - Mantén el fallback JavaScript para navegadores sin soporte.
- Prueba en una página larga para validar el cálculo de progreso.
HTML
<div id="kf-scroll-progress" role="progressbar" aria-label="Progreso de lectura" aria-valuemin="0" aria-valuemax="100"></div>
<style>
:root {
--progress-color: #3b82f6;
--progress-height: 3px;
--progress-z-index: 9999;
}
#kf-scroll-progress {
position: fixed;
top: 0;
left: 0;
height: var(--progress-height);
background: var(--progress-color);
z-index: var(--progress-z-index);
animation: scroll-progress linear;
animation-timeline: scroll(root block);
box-shadow: 0 0 10px var(--progress-color), 0 0 5px var(--progress-color);
width: 0%;
}
@keyframes scroll-progress {
from {
width: 0%;
}
to {
width: 100%;
}
}
.kf-progress-gradient #kf-scroll-progress {
background: linear-gradient(90deg, #3b82f6, #8b5cf6, #ec4899);
box-shadow: none;
}
@media (prefers-color-scheme: dark) {
:root {
--progress-color: #60a5fa;
}
}
@supports not (animation-timeline: scroll()) {
#kf-scroll-progress {
display: none;
}
}
</style>
<script>
(function() {
if (CSS.supports('animation-timeline', 'scroll()')) return;
const bar = document.getElementById('kf-scroll-progress');
if (!bar) return;
bar.style.display = 'block';
bar.style.width = '0%';
bar.style.transition = 'width 0.1s linear';
let rafId;
function updateProgress() {
const scrollTop = window.scrollY || document.documentElement.scrollTop;
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
const progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0;
bar.style.width = Math.min(progress, 100) + '%';
bar.setAttribute('aria-valuenow', Math.round(progress));
rafId = null;
}
window.addEventListener('scroll', function() {
if (!rafId) {
rafId = requestAnimationFrame(updateProgress);
}
}, { passive: true });
updateProgress();
})();
</script>
Prompt para Codex
TEXT
Crea una barra de progreso de lectura/scroll usando CSS Scroll-Driven Animations con fallback en JavaScript vanilla.
Implementación CSS principal:
- <div id="kf-scroll-progress"> fijo en top: 0, left: 0, ancho variable, height configurable
- CSS custom properties: --progress-color, --progress-height, --progress-z-index
- animation: scroll-progress linear con animation-timeline: scroll(root block)
- @keyframes scroll-progress de width: 0% a width: 100%
- box-shadow con glow effect del mismo color
- Variante .kf-progress-gradient con gradiente azul → morado → rosa
- @media prefers-color-scheme: dark con color más claro
- @supports not (animation-timeline: scroll()) que oculte el elemento (lo mostrará el JS fallback)
Fallback JavaScript:
- Verificar con CSS.supports si el navegador soporta animation-timeline
- Si soporta: retornar
- Si NO soporta: mostrar el elemento y agregar listener scroll con requestAnimationFrame
- Calcular: (scrollY / (scrollHeight - innerHeight)) * 100
- Actualizar width y aria-valuenow
Incluir role="progressbar" y aria-label en el HTML.
Salida: HTML del elemento + bloque <style> + <script> de fallback, todo listo para usar.