Sidebar to Overlay
Sidebar fixe qui se dilate en overlay plein écran avec transition cubic-bezier, backdrop blur et reflow automatique du contenu — une seule classe CSS déclenche tout.
Vous aurez accès à la démo interactive avec un compte gratuit.
Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Cartes comprend 41 effets, dont 6 gratuits. Découvrir la catégorie →
3 exemples d'usage
Comment ça marche
L'effet repose sur un basculement de position CSS relative → absolute piloté par la classe .overlay-mode. En mode normal, .sidebar-panel a width: 70px; position: relative; flex-shrink: 0 et occupe sa place dans le conteneur display: flex. Dès que .overlay-mode est ajouté, la propriété bascule en position: absolute; inset: 0; width: 100%; height: 100% — le panneau est arraché du flux et couvre toute la surface. .sidebar-main, régi par flex: 1 1 0%, récupère instantanément toute la largeur libérée et s'efface via transition: opacity .3s.
La transition .6s cubic-bezier(.4, 0, .2, 1) (Material Design easeInOut) s'applique aux propriétés interpolables uniquement : background, padding, et les dimensions des icônes (28 → 50 px, border-radius 6 → 10 px). En revanche, position et inset ne s'animent pas — ils sautent immédiatement à l'état cible, tandis que les couleurs et tailles glissent, créant l'impression d'une expansion organique.
.overlay-mode ajoute backdrop-filter: blur(4px) sur un fond rgba(99,102,241,0.15) semi-transparent. Le flou vitrifie le contenu derrière sans le masquer. Attention : backdrop-filter crée un stacking context qui isole les z-index des enfants de l'overlay du reste de la page.
Les étiquettes (.sidebar-label) utilisent transition: .4s .2s — durée 0,4 s avec un délai de 0,2 s. Elles attendent que l'expansion du panneau soit amorcée avant d'apparaître (font-size: 0; opacity: 0 → font-size: .55rem; opacity: 1), évitant le chevauchement visuel pendant le redimensionnement.
Accessibilité
- Pas de prefers-reduced-motion dans le code : la transition de 0,6 s joue même si l'OS demande à réduire le mouvement. À ajouter :
@media (prefers-reduced-motion: reduce) { .sidebar-panel, .sidebar-panel .sidebar-icon, .sidebar-panel .sidebar-label { transition: none } }. - Les boutons de bascule sont des
<button>natifs, focusables au clavier — mais aucunaria-expandedn'est mis à jour : l'état ouvert/fermé n'est pas annoncé aux lecteurs d'écran. - Le panneau et son wrapper ne portent ni
roleniaria-label: les lecteurs d'écran traversent les<div class="sidebar-icon">sans sémantique de navigation. - Contraste des étiquettes (
color: #a5b4fcsur fondrgba(99,102,241,0.2)) : ratio estimé ~3,2:1 — en dessous de WCAG AA (4,5:1) pour texte normal de moins de 18 pt. Acceptable si les labels sont traités comme décoratifs. - Navigation clavier : les deux boutons sont dans le flux de tabulation, activables sans JS supplémentaire.
Compatibilité navigateur
Requiert CSS Transitions et backdrop-filter. Les transitions sont universelles ; backdrop-filter est disponible dans tous les navigateurs modernes depuis 2022.
Sans backdrop-filter (Firefox < 103), l'overlay s'affiche avec le fond semi-transparent sans flou — l'effet reste fonctionnel. Sans transitions CSS, la permutation est instantanée mais l'état final est identique.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="demo-preview">
<div class="morph-toggle-group">
<button class="morph-toggle active" onclick="setSidebarMode(this,'sidebar')">Sidebar</button>
<button class="morph-toggle" onclick="setSidebarMode(this,'overlay')">Overlay</button>
</div>
<div class="sidebar-demo-wrapper">
<div class="sidebar-panel" id="sidebarPanel">
<div>
<div class="sidebar-icon"></div>
<span class="sidebar-label">Accueil</span>
</div>
<!-- Répétez pour chaque item -->
</div>
<div class="sidebar-main">
<div class="main-line"></div>
<!-- Contenu principal -->
</div>
</div>
</div>
HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
| .sidebar-panel { width } | 70px | Largeur de la sidebar en mode compact. Augmentez pour afficher des icônes plus grandes ou un libellé court toujours visible. |
| .sidebar-panel { transition } | .6s cubic-bezier(.4,0,.2,1) | Durée et courbe de la transition d'expansion. Remplacez par .3s ease pour une permutation plus vive, ou .9s pour un morphing plus lent. |
| .sidebar-panel.overlay-mode { backdrop-filter } | blur(4px) | Intensité du flou de verre sur le contenu derrière l'overlay. Passez à blur(0) pour un fond opaque, ou blur(12px) pour un verre épais. |
| .sidebar-panel.overlay-mode { background } | rgba(99,102,241,0.15) | Couleur de fond en mode overlay — ajustez la teinte et l'opacité à votre palette brand. |
| .sidebar-panel .sidebar-icon { width, height } | 28px | Taille des icônes en mode sidebar compact. La valeur overlay (50 px) est dans .overlay-mode .sidebar-icon — modifiez les deux en cohérence. |
| .sidebar-panel .sidebar-label (overlay) | font-size: .55rem | Taille des labels en mode overlay (0 en sidebar). Passez à .7rem pour une meilleure lisibilité sur grand écran. |
| .sidebar-main { transition } | opacity .3s | Durée du fondu du contenu principal lors de l'ouverture de l'overlay. Mettez none pour une disparition instantanée. |
FAQ
setSidebarMode est codé en dur sur getElementById('sidebarPanel'). Pour plusieurs instances, ajoutez un paramètre panelId à la fonction et passez-le depuis onclick : onclick="setSidebarMode(this,'overlay','sidebarPanel2')" — la modification tient en trois lignes.backdrop-filter: blur() est disponible dans Chrome 76+, Safari 9+, Edge 79+ et Firefox 103+. Sur Firefox antérieur à 103, l'overlay s'affiche avec le fond semi-transparent sans flou — toutes les transitions et le reflow fonctionnent normalement. Testez avec le flou désactivé pour vérifier la lisibilité du contenu derrière.document.getElementById('sidebarPanel').classList.add('overlay-mode') pour ouvrir, .classList.remove('overlay-mode') pour fermer. Synchronisez ensuite l'état actif des boutons via querySelectorAll('.morph-toggle') si l'UI doit le refléter.