In questo articolo implementeremo un indicatore di avanzamento della lettura con JavaScript.
Data l'altezza complessiva di un blocco di contenuto, un indicatore mostrerà l'avanzamento della lettura mentre l'utente scorre la pagina. Il calcolo tiene conto dell'altezza del viewport, dell'altezza del contenuto e dell'offset di scorrimento corrente.
Gli stili CSS di base impostano l'indicatore nella parte superiore della pagina. È costituito da una barra interna la cui larghezza cambierà in base al valore percentuale corrente ottenuto dal calcolo.
#progress-container {
position: fixed;
width: 100%;
height: 4px;
left: 0;
top: 0;
z-index: 1000;
background: transparent;
transition: all ease-out 0.2s;
}
#progress-container.ready {
transform: translateY(-3px);
}
#progress-bar {
display: block;
width: 0;
height: 3px;
background: #000;
}
Quindi dobbiamo effettivamente creare la struttura DOM corrispondente.
const addProgressBar = () => {
const element = document.createElement('div');
element.id = 'progress-container';
element.innerHTML = '<div id="progress-bar"></div>';
document.body.appendChild(element);
};
Ora possiamo creare la funzione principale.
const readingProgress = target => {
const winTop = window.pageYOffset || document.documentElement.scrollTop;
const targetBottom = target.offsetTop + target.scrollHeight;
const windowBottom = winTop + window.outerHeight;
const progress = 100 - (((targetBottom - windowBottom + window.outerHeight / 3) / (targetBottom - window.outerHeight + window.outerHeight / 3)) * 100);
document.querySelector('#progress-bar').style.width = progress + '%';
(progress > 100) ? document.querySelector('#progress-container').classList.add('ready') : document.querySelector('#progress-container').classList.remove('ready');
};
Infine possiamo inizializzare il codice quando il DOM è pronto.
document.addEventListener('DOMContentLoaded', () => {
const content = document.querySelector('#content');
addProgressBar();
readingProgress(content);
window.addEventListener('scroll', () => {
readingProgress(content);
});
});