Menu de navigation coulissant avec Popover
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>
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;
}
}