Offcanvas
L’offcanvas est un panneau qui glisse depuis un bord de l’écran, utile pour un menu mobile, des filtres ou un panier. Il garde la page visible derrière lui et se ferme par un bouton, Échap ou un clic sur le fond.
Exemple de base#
Un bouton data-bs-toggle="offcanvas" ciblant l'id du panneau l’ouvre. Un lien fonctionne aussi, avec href="#id" et role="button". Le panneau se compose d’un en-tête et d’un corps.
Compte courant : 1 250 000 FCFA
Compte épargne : 3 400 000 FCFA
Carte Visa Classic se terminant par 4821.
<div class="d-flex flex-wrap gap-2">
<a class="btn btn-primary" data-bs-toggle="offcanvas" href="#offcanvas-lien" role="button" aria-controls="offcanvas-lien">Ouvrir avec un lien</a>
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-bouton" aria-controls="offcanvas-bouton">Ouvrir avec un bouton</button>
</div>
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvas-lien" aria-labelledby="offcanvas-lien-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-lien-titre">Mes comptes</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">
<p>Compte courant : 1 250 000 FCFA</p>
<p>Compte épargne : 3 400 000 FCFA</p>
</div>
</div>
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvas-bouton" aria-labelledby="offcanvas-bouton-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-bouton-titre">Mes cartes</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">
<p>Carte Visa Classic se terminant par 4821.</p>
<button type="button" class="btn btn-outline-primary" data-bs-dismiss="offcanvas">Fermer le panneau</button>
</div>
</div>Positions#
Choisissez le bord avec .offcanvas-start (gauche), .offcanvas-end (droite), .offcanvas-top (haut) ou .offcanvas-bottom (bas). La largeur des panneaux latéraux est de 400 px, la hauteur des panneaux haut et bas de 30 vh.
<div class="d-flex flex-wrap gap-2">
<button class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-gauche">Gauche</button>
<button class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-droite">Droite</button>
<button class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-haut">Haut</button>
<button class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-bas">Bas</button>
</div>
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvas-gauche" aria-labelledby="offcanvas-gauche-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-gauche-titre">Panneau à gauche</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">Filtrer les opérations par période.</div>
</div>
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvas-droite" aria-labelledby="offcanvas-droite-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-droite-titre">Panneau à droite</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">Détail de la dernière opération.</div>
</div>
<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvas-haut" aria-labelledby="offcanvas-haut-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-haut-titre">Panneau en haut</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">Information importante sur les horaires d'agence.</div>
</div>
<div class="offcanvas offcanvas-bottom" tabindex="-1" id="offcanvas-bas" aria-labelledby="offcanvas-bas-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-bas-titre">Panneau en bas</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body small">Raccourcis : virement, paiement de facture, recharge mobile.</div>
</div>Fond et défilement#
Par défaut, le fond est affiché et la page ne défile plus. data-bs-scroll="true" laisse défiler la page ; data-bs-backdrop="false" retire le fond ; data-bs-backdrop="static" empêche la fermeture par clic sur le fond.
<div class="d-flex flex-wrap gap-2">
<button class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-defilement" data-bs-scroll="true" data-bs-backdrop="false">Défilement, sans fond</button>
<button class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-defilement-fond" data-bs-scroll="true">Défilement, avec fond</button>
<button class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-statique" data-bs-backdrop="static">Fond statique</button>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" data-bs-backdrop="false" tabindex="-1" id="offcanvas-defilement" aria-labelledby="offcanvas-defilement-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-defilement-titre">Page défilable</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">Vous pouvez faire défiler la page derrière ce panneau. Sans fond, le focus n'est pas piégé.</div>
</div>
<div class="offcanvas offcanvas-start" data-bs-scroll="true" tabindex="-1" id="offcanvas-defilement-fond" aria-labelledby="offcanvas-defilement-fond-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-defilement-fond-titre">Défilement avec fond</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">La page défile et le fond reste cliquable pour fermer.</div>
</div>
<div class="offcanvas offcanvas-end" data-bs-backdrop="static" tabindex="-1" id="offcanvas-statique" aria-labelledby="offcanvas-statique-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-statique-titre">Fond statique</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">Un clic à l'extérieur ne ferme pas ce panneau.</div>
</div>Couleurs#
Pour un panneau foncé, ajoutez .text-bg-dark et utilisez .btn-close-white pour que le bouton de fermeture reste visible.
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-sombre">Panneau foncé</button>
<div class="offcanvas offcanvas-end text-bg-dark" tabindex="-1" id="offcanvas-sombre" aria-labelledby="offcanvas-sombre-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-sombre-titre">Notifications</h2>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">Virement de 75 000 FCFA reçu ce matin.</div>
</div>Offcanvas responsive#
Remplacez .offcanvas par .offcanvas-{sm|md|lg|xl|xxl} : sous le point de rupture, le contenu est un panneau ; au-dessus, il s’affiche dans la page. Le bouton déclencheur doit alors être masqué avec d-lg-none.
<button class="btn btn-primary d-lg-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas-adaptatif" aria-controls="offcanvas-adaptatif">Afficher les filtres</button>
<div class="alert alert-info d-none d-lg-block mb-0">Affichage large : le contenu ci-dessous est dans la page, sans panneau.</div>
<div class="offcanvas-lg offcanvas-end" tabindex="-1" id="offcanvas-adaptatif" aria-labelledby="offcanvas-adaptatif-titre">
<div class="offcanvas-header">
<h2 class="offcanvas-title fs-5" id="offcanvas-adaptatif-titre">Filtres</h2>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#offcanvas-adaptatif" aria-label="Fermer"></button>
</div>
<div class="offcanvas-body">
<label class="form-label" for="offcanvas-filtre-type">Type d'opération</label>
<select class="form-select" id="offcanvas-filtre-type">
<option>Toutes</option>
<option>Virements</option>
<option>Retraits</option>
</select>
</div>
</div>Utilisation en JavaScript#
Ouvrez ou fermez le panneau depuis votre code et réagissez à ses événements.
const element = document.getElementById('offcanvas-bouton');
const panneau = new bootstrap.Offcanvas(element, {
backdrop: 'static',
scroll: false,
keyboard: true,
});
panneau.show();
element.addEventListener('hidden.bs.offcanvas', () => {
console.log('Panneau fermé');
});
// Plus tard
panneau.hide();Options
Options passées au constructeur ou par attribut (data-bs-backdrop, data-bs-keyboard, data-bs-scroll) sur le panneau ou sur son déclencheur.
| Option | Type | Défaut | Description |
|---|---|---|---|
backdrop | boolean | 'static' | true | Affiche un fond. 'static' : le fond ne ferme pas le panneau ; false : pas de fond. |
keyboard | boolean | true | Ferme le panneau avec la touche Échap. |
scroll | boolean | false | Autorise le défilement de la page pendant que le panneau est ouvert. |
Méthodes
| Méthode | Description |
|---|---|
toggle(relatedTarget) | Ouvre ou ferme le panneau. |
show(relatedTarget) | Ouvre le panneau. |
hide() | Ferme le panneau. |
dispose() | Détruit l’instance. |
bootstrap.Offcanvas.getInstance(element) | Renvoie l’instance liée à l’élément, ou null. |
bootstrap.Offcanvas.getOrCreateInstance(element, options) | Renvoie l’instance, ou la crée. |
Événements
| Événement | Déclenché quand |
|---|---|
show.bs.offcanvas | L’ouverture est demandée. relatedTarget contient le déclencheur. |
shown.bs.offcanvas | Le panneau est visible, transition terminée. |
hide.bs.offcanvas | La fermeture est demandée. |
hidePrevented.bs.offcanvas | La fermeture est bloquée (fond statique ou preventDefault()). |
hidden.bs.offcanvas | Le panneau est fermé, transition terminée. |
Classes et attributs data-bs-*
| Élément | Rôle |
|---|---|
.offcanvas, .offcanvas-{sm|md|lg|xl|xxl} | Le panneau (toujours, ou seulement sous le point de rupture). |
.offcanvas-start, .offcanvas-end, .offcanvas-top, .offcanvas-bottom | Bord d’où le panneau apparaît. |
.offcanvas-header, .offcanvas-title, .offcanvas-body | En-tête, titre et corps (le corps défile si le contenu est long). |
data-bs-toggle="offcanvas" | Sur le déclencheur : ouvre ou ferme le panneau ciblé. |
data-bs-target="#id" | Sur le déclencheur : sélecteur du panneau. |
data-bs-dismiss="offcanvas" | Sur un bouton du panneau : le ferme. |
data-bs-backdrop, data-bs-keyboard, data-bs-scroll | Options du panneau. |
Variables Sass
| Variable | Valeur par défaut |
|---|---|
$offcanvas-padding-y | $modal-inner-padding (1 rem) |
$offcanvas-padding-x | $modal-inner-padding (1 rem) |
$offcanvas-horizontal-width | 400px |
$offcanvas-vertical-height | 30vh |
$offcanvas-transition-duration | .3s |
$offcanvas-border-color | $modal-content-border-color |
$offcanvas-bg-color | var(--bs-body-bg) |
$offcanvas-color | var(--bs-body-color) |
$offcanvas-box-shadow | $modal-content-box-shadow-xs |
$offcanvas-backdrop-bg | $modal-backdrop-bg (noir) |
$offcanvas-backdrop-opacity | .5 |
Personnalisation#
Les variables CSS --bs-offcanvas-* se surchargent sur le panneau concerné.
// Sass : panneaux latéraux plus étroits
$offcanvas-horizontal-width: 320px;
$offcanvas-backdrop-opacity: 0.4;
// CSS : un panneau précis
.panneau-filtres {
--bs-offcanvas-width: 360px;
--bs-offcanvas-padding-x: 1.5rem;
--bs-offcanvas-bg: #F5F7FA;
}Bonnes pratiques
À faire
- Utilisez l’offcanvas pour du contenu secondaire : menu mobile, filtres, panier, aide.
- Donnez un titre au panneau et reliez-le avec
aria-labelledby. - Placez le panneau du côté où l’utilisateur l’attend : menu à gauche, panier ou notifications à droite.
- Gardez un bouton de fermeture visible, même si Échap fonctionne.
À éviter
- Ne l’utilisez pas pour une confirmation qui exige une réponse : préférez une modale.
- Ne placez pas de formulaires longs dans un panneau étroit.
- N’ouvrez pas un panneau automatiquement au chargement de la page.
Accessibilité
- À l’ouverture, Cauri ajoute
role="dialog"etaria-modal="true"et pose le focus sur le panneau ; à la fermeture, le focus revient au déclencheur. - Le focus est piégé dans le panneau tant que le fond est actif ou que
scrollest faux. Avecdata-bs-scroll="true"etdata-bs-backdrop="false", le focus circule librement : fournissez alors un moyen de fermeture évident. - Échap ferme le panneau, sauf si
keyboardvautfalse. - Mettez
tabindex="-1"sur le panneau pour qu’il puisse recevoir le focus. - Un bouton
.btn-closesans texte doit avoir unaria-label.