CSS only menu toggle - is this a good way to approach it?

For years I've used jQuery slideUp/Down/Toggle() for showing menus on mobile devices. However, recently I've started using :has selectors more and that's opening up the possibility to do CSS-only versions: - My menu toggle button becomes a label containing a checkbox (hidden). When you click the label, it checks the checkbox - The menu css has:
.my-menu {
display: none;
}

body:has(input#menu-toggle[type=checkbox]:checked) .my-menu {
display: block;
}
.my-menu {
display: none;
}

body:has(input#menu-toggle[type=checkbox]:checked) .my-menu {
display: block;
}
Is this a good way to approach it, or should I stick to some javascript anyway as I should be setting aria-expanded etc (which could also drive the CSS)? What other drawbacks might I be missing here?
4 Replies
glutonium
glutonium14mo ago
using checkbook as a click listener is quite an old trick.. and it doesn't necessarily require the has selector u can do it with the general selector ~
<!DOCTYPE html>
<html>
<head>
<style>
*{
margin : 0;
padding : 0;
box-sizing : border-box;
}

body{
background : #1b1b1b;
}

.navIcon{
height : 50px;
width : 50px;
background : coral;
position : fixed;
top : 10px;
right : 20px;
}

#check{
display : none;
}

.sideMenu{
height : 100vh;
width : 70vw;
background : wheat;
position : fixed;
top :0;
transform : translateX(-100%);
transition : 300ms;
}

#check:checked ~ .sideMenu{
transform : translateX(0)
}

</style>
</head>
<body>
<div class = "container">
<label for="check">
<div class = "navIcon"></div>
</label>
<input type="checkbox" id="check">
<div class = "sideMenu"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style>
*{
margin : 0;
padding : 0;
box-sizing : border-box;
}

body{
background : #1b1b1b;
}

.navIcon{
height : 50px;
width : 50px;
background : coral;
position : fixed;
top : 10px;
right : 20px;
}

#check{
display : none;
}

.sideMenu{
height : 100vh;
width : 70vw;
background : wheat;
position : fixed;
top :0;
transform : translateX(-100%);
transition : 300ms;
}

#check:checked ~ .sideMenu{
transform : translateX(0)
}

</style>
</head>
<body>
<div class = "container">
<label for="check">
<div class = "navIcon"></div>
</label>
<input type="checkbox" id="check">
<div class = "sideMenu"></div>
</div>
</body>
</html>
glutonium
glutonium14mo ago
glutonium
glutonium14mo ago
i haven't yet cleared the concept of :has so i made with general selector ~
13eck
13eck14mo ago
As boob said, using a checkbox is a very old trick with a long history. But I would advise against using :has() for now as browser support isn’t quite there yet. It’s not supported in Firefox: https://caniuse.com/css-has Also, a good article on progressive enhancement for a slide-in nav menu: https://gomakethings.com/progressive-enhancement-the-new-hotness/