Table des matières¶
Génération automatique de la table des matières à partir des titres de la page avec mise en évidence de la section active.

Le panneau On this page à droite est la table des matières, construite à partir des titres h2–h6 de la page.
Vue d'ensemble¶
- Auto-générée : Extraite des titres h2-h6
- Scroll Spy : Met en évidence la section courante
- Défilement fluide : Navigation animée
- Responsive : Barre latérale sur ordinateur, offcanvas sur mobile
Implémentation¶
Modèle d'inclusion¶
Génération de la TOC¶
L'include toc.html utilise la TOC intégrée de Kramdown :
{% raw %}<nav id="TableOfContents" class="toc">
<h2 class="toc-title">On This Page</h2>
{{ content | toc_only }}
</nav>{% endraw %}
Ou une extraction manuelle :
{% raw %}<nav id="TableOfContents">
<ul class="toc-list">
{% for heading in page.content | split: '<h' %}
{% if heading contains 'id="' %}
{% assign id = heading | split: 'id="' | last | split: '"' | first %}
{% assign level = heading | slice: 0, 1 %}
{% assign text = heading | split: '>' | last | split: '<' | first %}
<li class="toc-item toc-level-{{ level }}">
<a href="#{{ id }}" class="toc-link">{{ text }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</nav>{% endraw %}
Configuration¶
Activer la TOC¶
Dans le front matter :
Ou à l'échelle du site dans _config.yml :
Niveaux de titres¶
Configurer les titres à afficher :
Style¶
Styles de base¶
.toc {
position: sticky;
top: 80px;
max-height: calc(100vh - 100px);
overflow-y: auto;
}
.toc-title {
font-size: 0.875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 1rem;
}
.toc-list {
list-style: none;
padding: 0;
margin: 0;
}
.toc-link {
display: block;
padding: 0.25rem 0;
color: var(--bs-secondary);
text-decoration: none;
font-size: 0.875rem;
border-left: 2px solid transparent;
padding-left: 0.75rem;
}
.toc-link:hover {
color: var(--bs-primary);
}
.toc-link.active {
color: var(--bs-primary);
border-left-color: var(--bs-primary);
font-weight: 500;
}
Niveaux imbriqués¶
Scroll Spy¶
Intersection Observer¶
function initScrollSpy() {
const headings = document.querySelectorAll('h2[id], h3[id], h4[id]');
const tocLinks = document.querySelectorAll('.toc-link');
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
tocLinks.forEach((link) => link.classList.remove('active'));
const activeLink = document.querySelector(
`.toc-link[href="#${entry.target.id}"]`
);
activeLink?.classList.add('active');
}
});
},
{ rootMargin: '-20% 0% -70% 0%' }
);
headings.forEach((heading) => observer.observe(heading));
}
Défilement fluide¶
Méthode CSS¶
Méthode JavaScript¶
document.querySelectorAll('.toc-link').forEach((link) => {
link.addEventListener('click', (e) => {
e.preventDefault();
const targetId = link.getAttribute('href').slice(1);
const target = document.getElementById(targetId);
const headerOffset = 80;
const position = target.offsetTop - headerOffset;
window.scrollTo({
top: position,
behavior: 'smooth'
});
history.pushState(null, '', `#${targetId}`);
});
});
Comportement responsive¶
Ordinateur¶
La TOC apparaît dans la barre latérale droite :
Mobile¶
TOC en offcanvas (voir Mobile TOC) :
<div class="offcanvas offcanvas-end d-lg-none" id="tocSidebar">
{% raw %}{% include content/toc.html %}{% endraw %}
</div>
Accessibilité¶
Attributs ARIA¶
Navigation au clavier¶
- Tabulation à travers les liens de la TOC
- Entrée pour naviguer vers la section
- Le focus se déplace vers le titre
Dépannage¶
La TOC ne se génère pas¶
- Vérifiez que les titres ont des ID
- Vérifiez
toc: truedans le front matter - Assurez-vous d'utiliser le processeur Kramdown
Le Scroll Spy ne fonctionne pas¶
- Vérifiez que les ID des titres correspondent aux href de la TOC
- Vérifiez la prise en charge d'Intersection Observer
- Testez les marges de l'observer
Problèmes de style¶
- Vérifiez le positionnement sticky
- Vérifiez le z-index
- Testez le comportement d'overflow
Voir aussi¶
Voir aussi¶
- [[Features]]
- [[Mobile TOC Floating Action Button]]
- [[Sidebar Navigation System]]