Scrollspy-navigatie is een veelvoorkomend UI-patroon dat automatisch de navigatielink markeert die overeenkomt met het gedeelte van de pagina dat op dat moment in de viewport staat. Zo weten gebruikers waar ze zich bevinden in een lang document terwijl ze scrollen.
Dit patroon komt vaak voor in 2 scenario's:
- Websites met één pagina: Waar de primaire sitenavigatie naar verschillende gedeelten van één pagina linkt in plaats van naar afzonderlijke URL's.
- Lange content: Waarbij een inhoudsopgave of zijbalknavigatie de voortgang van de gebruiker bijhoudt in een artikel, gids of documentatie.
Hoe wordt dit geïmplementeerd
Traditioneel vereiste het scrollspy-patroon JavaScript en de IntersectionObserver API. Moderne CSS biedt een native manier om dit te bereiken met de property scroll-target-group en de pseudoklasse :target-current.
- Zorg dat navigatielinks fragment-ID's gebruiken: Je navigatie moet bestaan uit ankerlinks (
<a>) die verwijzen naar gedeelten op dezelfde pagina met fragment-ID's (bijvoorbeeld<a href="#section-1">) die overeenkomen met deidvan je contentgedeelten. - Scroll Target Grouping aanzetten: Pas de property
scroll-target-group: autotoe op de container van uw navigatielinks. Hiermee wordt de browser verteld deze links te behandelen als markeringen die hun respectieve doelen bijhouden. - De actieve link opmaken: Gebruik de pseudoklasse
:target-currentvoor je navigatielinks om stijlen toe te passen als het doelgedeelte zichtbaar is in de scrollcontainer. - Semantische status: Gebruik een script om
aria-current="true"op de actieve link te updaten als het scrollen stopt, zodat de status correct wordt doorgegeven aan ondersteunende technologieën.
Voorbeeldcode
In dit voorbeeld wordt de actieve link in een vast navigatiemenu gemarkeerd terwijl de gebruiker door gedeelten scrollt.
/* MANDATORY: The container of markers must have scroll-target-group: auto */
nav {
/* Enables automatic tracking of fragment links */
scroll-target-group: auto;
}
/* MANDATORY: Use :target-current to style the link whose target is in view. */
nav a:target-current {
color: var(--accent, #007bff);
border-bottom-color: var(--accent, #007bff);
}
<nav>
<a href="#intro">Introduction</a>
<a href="#features">Features</a>
<a href="#pricing">Pricing</a>
</nav>
<main>
<!-- MANDATORY: Each section must have a unique ID matching a link fragment in the <nav>. -->
<section id="intro">
<h2>Introduction</h2>
<!-- content -->
</section>
<section id="features">
<h2>Features</h2>
<!-- content -->
</section>
<section id="pricing">
<h2>Pricing</h2>
<!-- content -->
</section>
</main>
<script type="module">
if (CSS.supports('scroll-target-group: auto')) {
const syncAriaCurrent = () => {
const currentLink = document.querySelector('nav a:target-current');
document.querySelectorAll('nav a').forEach(link => {
link.setAttribute('aria-current', link === currentLink ? 'true' : 'false');
});
};
// Update the aria on initial page load. Ensure the DOM content is loaded, either by using `<script type="module">` or an event listener for `DOMContentLoaded`.
syncAriaCurrent();
// Update the aria after scroll ends
document.addEventListener('scrollend', syncAriaCurrent);
}
</script>
Praktische tips
- Gebruik WEL
scroll-target-group: autoin een speciale container voor navigatielinks: Zo weet de browser welke links moeten worden bijgehouden. - ZORG dat doelen unieke
id-kenmerken hebben die overeenkomen met dehref-kenmerken van de links. - Zorg WEL voor voldoende verticale ruimte voor secties:
scroll-target-groupgeeft het zichtbare doel het duidelijkst aan als secties groot genoeg zijn zodat er maar één of twee tegelijk zichtbaar zijn. - VERPLICHT: Voor toegankelijkheid moet de visuele status worden gespiegeld met
aria-current.:target-currentverwerkt het visuele aspect, maar dit wordt niet weergegeven aan schermlezers. - Vertrouw AVOID alleen op kleur voor de actieve status: gebruik andere visuele aanwijzingen, zoals lettertypegrootte, een onderstreping of een indicatorstip, of zorg dat er voldoende contrast is tussen de kleuren, zodat het verschil toegankelijk is voor gebruikers met kleurenblindheid.
Reservestrategieën
Voor browsers die scroll-target-group niet ondersteunen, moet je een fallback gebruiken op basis van de IntersectionObserver API.
<script>
// Feature detection for scroll-target-group
const supportsScrollTargetGroup = CSS.supports('scroll-target-group: auto');
if (!supportsScrollTargetGroup) {
const navLinks = document.querySelectorAll('nav a');
const sections = document.querySelectorAll('main section');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const id = entry.target.getAttribute('id');
navLinks.forEach(link => {
const isActive = link.getAttribute('href') === `#${id}`;
// Use the escaped colon class for consistent styling
link.classList.toggle('\:target-current', isActive);
link.setAttribute('aria-current', isActive);
});
}
});
}, { rootMargin: '-50% 0px -50% 0px', threshold: 0 });
sections.forEach(section => observer.observe(section));
}
</script>
<style>
/* Fallback style if :target-current is not supported.
Use :is() to combine the native pseudo-class with a fallback class for older browsers. DO NOT use `nav a:target-current, nav a.\:target-current, as the unrecognized pseudoselector invalidates the entire rule in older browsers. */
nav a:is(:target-current, .\:target-current) {
color: var(--accent, #007bff);
border-bottom-color: var(--accent, #007bff);
font-weight: bold;
}
</style>