Démos

Menu de navigation coulissant avec Popover

01

HTML

index.html
<div class="content"> <header> <h1>Menu de navigation avec Popover</h1> <button popovertarget=menu> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /> </svg> <span class="sr-only">Toggle Menu</span> </button> </header> <main> <p>Link to the doc <a href="https://developer.mozilla.org/fr/docs/Web/API/Popover_API" >MDN</a></p> <p>No Javascript for this demo 🔥</p> <p>Compatible with Firefox, Chrome, Edge and Safari (<a href="https://caniuse.com/mdn-api_htmlelement_popover">caniuse</a>)</p> </main> </div> <div popover id="menu" role="menu"> <nav> <a autofocus href="#"><span>Home</span></a> <a href="#"><span>Contact</span></a> <a href="#"><span>Showcase</span></a> <a href="#"><span>Blog</span></a> <a href="#"><span>About</span></a> </nav> </div>
02

CSS

style.css
@layer demo { [popovertarget] { background: transparent; color: black; position: fixed; top: 1rem; right: 1rem; inline-size: 48px; aspect-ratio: 1; &:is(:hover, :focus-visible) { background: #e9ecef; } svg { stroke-width: 2; stroke: white; &:is(:hover, :focus-visible){ stroke: black; } } } body:has(#menu:popover-open) .content { translate: -220px 0; } [popover] { overflow: hidden; border: none; &::backdrop { background: hsl(0 0% 85% / 0.5); backdrop-filter: blur(4px); opacity: var(--open, 0); transition: opacity 5s, display 0.2s, overlay 0.2s; } } @media (prefers-reduced-motion: no-preference) { [popover]:is(:popover-open, :popover-open::backdrop ) { @starting-style { --open: 0; } --open: 1; } } } @layer demoStyles { :root { --padding: 1rem; --transition: 0.165s; --red: #e1163c; } *::before, *::after { box-sizing: border-box; } *:not(dialog) { margin: revert; padding: revert; } body { align-items: normal; justify-content: normal; color: white; } .content { padding-top: 4rem; display: grid; place-items: center; align-content: start; transition: translate 0.2s; h1 { margin-bottom: 2rem; font-size: 3rem; font-weight: 900; } p { font-size: 1.5rem; } a { color: var(--red); } main { display: grid; align-items: center; gap: 1rem; } svg { width: 48px; z-index: 2; } button { border: 0; padding: 0; } } #menu { background: white; margin: 0; padding: 1rem; align-items: center; justify-content: center; gap: 1rem; position: fixed; inset: unset; top: 0; left: 100%; height: 100vh; width: 220px; border-radius: 0; transition: display 0.2s, overlay 0.2s, translate 0.2s; translate: calc(var(--open, 0) * -100%) 0; nav { display: grid; text-transform: uppercase; gap: 0.5rem; a { padding: 0.25rem; color: black; font-size: 1.5rem; text-decoration: none; position: relative; &:after { content: ""; position: absolute; left: 0; top: 50%; translate: 0 -50%; height: 4px; width: 0.8ch; background: var(--red); transition: scale 0.2s; scale: 0 1; transform-origin: 0 50%; } &:focus-visible { outline-color: red; } span { display: inline-block; transition: translate 0.2s; } &:is(:hover, :focus-visible) { &:after { scale: 1 1; } span { translate: 1ch 0; } } } } } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } }