⚡ Interactieve componenten
Modals, dropdowns, accordions en toasts — Bootstrap JS doet het werk.
Hoe Bootstrap JS werkt
Interactieve componenten — modals, dropdowns, accordions — werken in Bootstrap 5 bijna zonder dat je zelf JavaScript schrijft.
Je voegt speciale data-bs-* attributen toe aan je HTML, en Bootstrap JS regelt de rest.
<button id="openBtn">Open modal</button>
<div id="modal" style="display:none">...</div>
<script>
document.getElementById('openBtn')
.addEventListener('click', () => {
document.getElementById('modal')
.style.display = 'block';
});
</script>
Zelf wiring, styling, backdrop, keyboard support schrijven
<button data-bs-toggle="modal"
data-bs-target="#myModal">
Open modal
</button>
<div class="modal" id="myModal">
...
</div>
Geen eigen JS nodig — Bootstrap regelt alles
Interactieve componenten vereisen Bootstrap JS. Laad het altijd voor </body> — het "bundle" bestand bevat ook Popper.js (nodig voor dropdowns en tooltips).
<!-- In <head> — stijlen -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
<!-- Voor </body> — interactiviteit -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js">
</script>
data-bs-* attributendata-bs-toggle="modal"
Klik opent/sluit een modal
data-bs-target="#id"
Welk element wordt getoggled
data-bs-toggle="dropdown"
Klik opent dropdown-menu
data-bs-toggle="collapse"
Klik klapt element in/uit (accordion)
data-bs-dismiss="modal"
Sluit de huidige modal
data-bs-parent="#id"
Sluit andere items in groep (accordion)
Modals
Een modal is een dialoogvenster dat bovenop de pagina zweeft. Bootstrap regelt backdrop, animatie, focustrap en keyboard-sluiting (Escape).
<!-- Trigger knop -->
<button class="btn btn-primary"
data-bs-toggle="modal"
data-bs-target="#bevestigModal">
Verwijder account
</button>
<!-- Modal HTML (buiten andere containers, voor </body>) -->
<div class="modal fade" id="bevestigModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Weet je het zeker?</h5>
<button type="button" class="btn-close"
data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Dit kan niet ongedaan worden gemaakt.</p>
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-bs-dismiss="modal">Annuleren</button>
<button class="btn btn-danger">Verwijderen</button>
</div>
</div>
</div>
</div>
<div class="modal-dialog modal-lg">
<div class="modal-dialog
modal-dialog-centered">
Modal wordt verticaal gecentreerd in het scherm
<div class="modal-dialog
modal-dialog-scrollable">
Body scrollt, header/footer blijven vast
Soms wil je een modal vanuit JavaScript openen (bijv. na een fetch-call):
// Haal Bootstrap-instantie op en gebruik .show() / .hide()
const modalEl = document.getElementById('bevestigModal');
const modal = new bootstrap.Modal(modalEl);
modal.show(); // openen
modal.hide(); // sluiten
Dropdowns
Een dropdown toont een menu op klik. Bootstrap gebruikt Popper.js (ingebouwd in het bundle-bestand) voor de positionering.
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle"
data-bs-toggle="dropdown">
Acties
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Bewerken</a></li>
<li><a class="dropdown-item" href="#">Dupliceren</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="#">Verwijderen</a></li>
</ul>
</div>
<div class="dropup">...</div>
<div class="btn-group">
<button class="btn btn-primary">
Opslaan
</button>
<button class="btn btn-primary
dropdown-toggle
dropdown-toggle-split"
data-bs-toggle="dropdown">
</button>
<ul class="dropdown-menu">...</ul>
</div>
Accordion
Een accordion klapt secties open en dicht. Ideaal voor FAQ's, instellingen of uitgebreide navigatie. Elke sectie bestaat uit een header (knop) en een collapsible body.
<div class="accordion" id="faqAccordion">
<!-- Item 1 -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button"
data-bs-toggle="collapse"
data-bs-target="#vraag1">
Wat is Bootstrap?
</button>
</h2>
<div id="vraag1" class="accordion-collapse collapse show"
data-bs-parent="#faqAccordion">
<div class="accordion-body">
Bootstrap is een CSS-framework...
</div>
</div>
</div>
<!-- Item 2 -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed"
data-bs-toggle="collapse"
data-bs-target="#vraag2">
Werkt het met Symfony?
</button>
</h2>
<div id="vraag2" class="accordion-collapse collapse"
data-bs-parent="#faqAccordion">
<div class="accordion-body">
Ja, via bootstrap_5_layout.html.twig...
</div>
</div>
</div>
</div>
collapse show— item begint opencollapse— item begint dichtcollapsedop knop — knop-stijl voor dicht itemdata-bs-parent="#id"— alleen één item tegelijk open
Laat data-bs-parent weg als je meerdere items tegelijk open wilt kunnen hebben.
Handig voor lange instellingspagina's waar de gebruiker meerdere secties wil vergelijken.
Toasts
Toasts zijn korte meldingen die even verschijnen en dan verdwijnen — vergelijkbaar met Symfony flash messages, maar dan client-side.
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div id="mijnToast" class="toast" role="alert">
<div class="toast-header">
<strong class="me-auto">Melding</strong>
<small>Nu</small>
<button type="button" class="btn-close"
data-bs-dismiss="toast"></button>
</div>
<div class="toast-body">
Opgeslagen! ✓
</div>
</div>
</div>
Je moet een toast programmatisch tonen met JavaScript:
// Toon een toast na een actie (bijv. formulier opgeslagen)
function toonToast(id) {
const toastEl = document.getElementById(id);
const toast = new bootstrap.Toast(toastEl);
toast.show();
}
// Optie: automatisch verdwijnen instellen (in ms)
const toast = new bootstrap.Toast(toastEl, { delay: 3000 });
Symfony flash messages (app.flashes()) zijn server-side — de pagina reloadt.
Bootstrap Toasts zijn client-side — geen reload nodig. Combineer ze voor de beste UX:
{# In Twig: flash messages als Bootstrap toasts #}
{% for message in app.flashes('success') %}
<div id="flashToast-{{ loop.index }}" class="toast align-items-center text-bg-success border-0" role="alert">
<div class="d-flex">
<div class="toast-body">{{ message }}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto"
data-bs-dismiss="toast"></button>
</div>
</div>
{% endfor %}
<script>
// Auto-toon alle flash toasts
document.querySelectorAll('.toast').forEach(el => {
new bootstrap.Toast(el, { delay: 4000 }).show();
});
</script>
Oefening 1 — Productpagina
Bouw een productdetailpagina met:
- Een dropdown knop "Kleur kiezen" met 3 opties
- Een knop "Meer info" die een modal opent met producttekst
- Een knop "In winkelwagen" die een groene toast toont ("Toegevoegd!")
Tip: je hebt data-bs-toggle, data-bs-target, en new bootstrap.Toast() nodig.
Oplossing tonen
<div class="d-flex gap-2 flex-wrap mb-3">
<!-- Dropdown -->
<div class="dropdown">
<button class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">
Kleur kiezen
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Zwart</a></li>
<li><a class="dropdown-item" href="#">Wit</a></li>
<li><a class="dropdown-item" href="#">Blauw</a></li>
</ul>
</div>
<!-- Modal trigger -->
<button class="btn btn-info" data-bs-toggle="modal" data-bs-target="#infoModal">Meer info</button>
<!-- Toast trigger -->
<button class="btn btn-success" onclick="new bootstrap.Toast(document.getElementById('cartToast'),{delay:3000}).show()">
In winkelwagen
</button>
</div>
<!-- Modal -->
<div class="modal fade" id="infoModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Productinformatie</h5>
<button class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Materiaal: aluminium behuizing. Gewicht: 1.2 kg. Garantie: 2 jaar.</p>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" data-bs-dismiss="modal">Sluiten</button>
</div>
</div>
</div>
</div>
<!-- Toast -->
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div id="cartToast" class="toast align-items-center text-bg-success border-0">
<div class="d-flex">
<div class="toast-body">Toegevoegd aan winkelwagen!</div>
<button class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
</div>
</div>
</div>
Oefening 2 — FAQ-pagina
Bouw een FAQ-pagina met:
- Een accordion met 4 vragen (waarvan de eerste standaard open is)
- Een navbar met een dropdown "Meer" met twee links
- Alles in een container, mooi opgemaakt
Oplossing tonen
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">MijnSite</a>
<div class="navbar-nav ms-auto">
<a class="nav-link" href="#">Home</a>
<a class="nav-link active" href="#">FAQ</a>
<div class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">Meer</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Over ons</a></li>
<li><a class="dropdown-item" href="#">Contact</a></li>
</ul>
</div>
</div>
</div>
</nav>
<div class="container py-5">
<h1 class="mb-4">Veelgestelde vragen</h1>
<div class="accordion" id="faq">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button" data-bs-toggle="collapse" data-bs-target="#q1">Vraag 1</button>
</h2>
<div id="q1" class="accordion-collapse collapse show" data-bs-parent="#faq">
<div class="accordion-body">Antwoord 1</div>
</div>
</div>
<!-- herhaal voor q2, q3, q4 -->
</div>
</div>
🧠 Kennischeck
Les 6 afgerond!
Je beheerst modals, dropdowns, accordions en toasts — de interactieve kern van Bootstrap.