Voortgangsindicator met JS en CSS
Hierboven zie je een lichtgrijze balk. Die zit bovenaan het document vastgepind . Als je tijdens het lezen naar beneden scrollt verschijnt daarin een indicator die aangeeft hoeveel van het document je al gezien hebt.
Op deze bladzijde wordt getoond hoe je zoiets maakt. De code van het voorbeeld kun je downloaden om zelf te gebruiken.
Dit is een bewerking van een script dat ik aantrof in Webdesigner Magazine nr. 93 (februari 2017), pag. 24 e.v. Dit
blad wordt sinds eind november 2017 niet meer gemaakt.
Het oorspronkelijke script is gemaakt door Jorrit Tinholt en is te vinden op CodePen.
Voor deze site heb ik de code wat gefatsoeneerd en een kleine onvolkomenheid uit het JavaScript gehaald.
- Er worden twee items besproken:
- De werking van het script.
- Inbouwen in je eigen document.
- De werking van het script
- De oorspronkelijke versie van het script heeft een onhebbelijkheid: De balk komt bij omhoogscrollen niet terug naar nul, maar blijft ergens op ⅓ hangen. Dat is in de versie op deze pagina gecorrigeerd.
- Om een voor mij onduidelijke reden loopt de balk pas goed als deze voor ca. 30% zichtbaar is. Dat is met een trucje opgelost.
- De code van het voorbeeld bestaat uit HTML (in het document), CSS voor de opmaak van de balk en de animatie (in de file
styles.css) en JavaScript om te reageren op scroll-acties (in het document).
- HTML
- De HTML heeft een bepaalde structuur. Die moet intact blijven om het te laten werken.
- De eerste tag in de body is <article>; deze heeft de klasse js-article. Dat geldt althans voor het voorbeeld. In plaats van article kun je ook een ander blok-element nemen, zoals main. 'Kleine' blok-elementen zoals p raad ik af, maar het kan wel.
- Direct binnen het <article> is er een <div> met klasse progress-container. Dit de voortgangsindicator, of beter gezegt: de lijst ervan. De de div dient om de indicator te positioneren op het scherm
- Binnen de <div> met klasse progress-container bevindt zich een <div> met klassen progress-bar
en js-progress-bar. Dit is de blauwe balk. De klasse progress-bar dient voor de opmaak. De klasse js-progress-bar
dient voor de communicatie met het JavaScript.
- CSS
- De progress-container is hier ingesteld op een breedte van 500px. Voor deze website is dat prima, maar voor je eigen toepassing kun je natuurlijk een bredere of smallere balk instellen.
- De grijze rand die om de blauwe streep blijft staan is 10px breed. Dat is ingesteld met padding.
- De balk wordt in het midden van het document gehouden met een variatie op een oud trucje: Hij wordt naar links geschoven over 50% van de breedte van het document en wordt vervolgens over de helft van de breedte van de balk teruggeschoven met behulp van transform: translateX(-50%).
- De progress-container is bovenaan het document vast gepind met behulp van top:0 en position:fixed.
- De blauwe streep zelf ontstaat met progress-bar. De breedte staat aanvankelijk op 0%, maar die wordt door het JavaScript veranderd.
- De hoogte van de balk (de breedte van de streep) is hier 10px, maar dat kun je anders instellen. Voor een zeer subtiel effect maak je de hoogte 1px of 2px en zet je de padding in progress-container op 2px of 3px.
- Als de lengte van de blauwe streep wordt veranderd, gaat dat via een transition.
Deze duurt 0.25 seconde en verloopt als ease. Dat geeft hier het leukste effect.
- Om te voorkomen dat de balk een paar regels van de content in het document bedekt, is een geschikte padding ingesteld
voor het body-element.
- JavaScript
- Het JavaScript doet —kort gezegd— het volgende:
• Bij elke scroll-actie wordt berekend hoever er is gescrolled, uitgedrukt in het percentage van de lengte van het document.
• Dat percentage is de breedte van de voortgangsindicator.
- Allereerst worden de variabelen article en progressbar gemaakt. Die bevatten verwijzingen naar de de klassen js-article en js-progress-bar. Ofwel naar de content van het document en de voortgangsindicator.
- Daarna worden de functions getHeight(), getValue() en getPercentage() gedefinieerd. Die zorgen voor
het rekenwerk:
• getHeight() bepaalt de hoogte van het article-element;
• getValue() bepaalt hoever er is gescrolled;
• getPercentage() bepaalt hoeveel procent er is gescrolled. - Tenslotte wordt de function onScroll() gemaakt. Die is via aadEventListener() aan het scroll-event gekoppeld.
Deze function roept getPercentage() aan een zet het resultaat in de scrollbalk.
- Inbouwen in je eigen document
- Download de .zip-file en pak hem uit.
- Bouw de code op zoals hieronder is aangegeven.
- Pas de kleuren aan aan je eigen wensen.
- Pas de afmetingen van de balk aan aan je eigen wensen. Dat de je door in progress-container de waarde van width te veranderen. Breedte van de balk verander je door de waarde van height in progress-bar te verhogen of te verlagen.
- Het is mogelijk de balk onderaan het scherm te zetten dat doe je door in progress-container de regeltop: 0; te vervangen door bottom: 0;.
Gebruik:
- De code staat gedeeltelijk in de <HEAD> en gedeeltelijk in de <BODY>.
De code van het voorbeeld ziet er als volgt uit:
(Zet dit in de <HEAD>).
<link rel="stylesheet" href="styles.css">
(Zet dit net na de <BODY>-tag).
<article class="js-article">
<div class="progress-container">
<div class="progress-bar js-progress-bar"></div>
</div>
(Zet dit net vóór de </BODY>-tag).
</article>
<script>
var article = document.querySelector('.js-article');
var progressbar = document.querySelector('.js-progress-bar');
function getHeight() {
return article.offsetHeight; // hoogte van het element in variabele article
};
function getValue() { // hoever is er gescrolled?
if (window.scrollY < window.innerHeight/10) { // minder dan 10%
return 0;
} else if (window.scrollY < window.innerHeight/5) { // minder dan 20%
return .2 * getHeight();
} else if (window.scrollY < window.innerHeight/3) { // minder dan 33%
return .33 * getHeight();;
} else {
return window.innerHeight - (article.offsetTop - window.scrollY);
}
};
function getPercentage() {
var percentage = (getValue() / getHeight()) * 100;
return Math.max(0, Math.min(100, percentage));
};
function onScroll() {
progressbar.style.width = getPercentage() + '%';
}; window.addEventListener('scroll', onScroll);
</script>