In today's example will build a pure CSS dropdown menu using the :focus-within
pseudo-class.
You can see in the video below the working example:
How does the :focus-within CSS pseudo selector work
The :focus-within selects an element if that element contains any children that are focused.
It is related to the :focus
pseudo class, just that it will fire if something that is contained within that element is selected.
Unlike :focus
, which is applied directly to the element itself the :focus-within
rules are applied to the parent of the focused element.
Making a dropdown CSS menu with :focus-within
In order to build the menu we will start with a basic HTML structure like the one below:
<div class="menu-container">
<div class="menu" tabindex="0">
<p>β° Dropdown menu</p>
<div class="menu-content">
<a href="#">πΌ Services</a>
<a href="#">π° Business</a>
</div>
</div>
</div>
Will add just a bit of CSS to make the initial look of the menu:
.menu-container {
display: inline-flex;
flex-direction: row;
border: solid 2px #000000;
cursor: pointer;
}
.menu {
position: relative;
padding: 0rem 0.5rem;
}
.menu > .menu-content {
display: none;
}
At this moment we will just have just the menu shown but without the working dropdown:
The reason why we need to use tabindex="0"
is so that the menu will be selectable id the user navigates with a keyboard.
In order to add the dropdown will add the extra rules based on the :focus-within
pseudo-class:
.menu > .menu-content {
display: none;
position: absolute;
border: solid 2px #000000;
}
.menu:focus-within > .menu-content {
display: flex;
flex-direction: column;
}
.menu a {
padding: 0.5rem;
display: inline-block;
color: #000000;
}
At this point, if we click on the menu we will see the dropdown working.
If we would have just .menu:focus > .menu-content
the dropdown menu would have closed while navigating the items from that dropdown. Therefore the need to use :focus-within
.
Check out the full working codepen here.
Adding nested dropdown menus
One nice thing about this approach is that we can just include the HTML for a submenu:
<div class="menu-container">
<div class="menu" tabindex="0">
<p>β° Dropdown menu</p>
<div class="menu-content">
<a href="#">πΌ Services</a>
<a href="#">π° Business</a>
<div class="menu" tabindex="0">
<p>π Books menu</p>
<div class="menu-content">
<a href="#">π Red</a>
<a href="#">π Green</a>
</div>
</div>
</div>
</div>
</div>
And it will work as expected:
Check out the full working codepen here and also you can see here another exmple of how we canΒ use focus-within with forms.
The browser support for :focus-within
Overall the browser support is great for the :focus-within
pseudo-class, so we should not have any compatibility issues.
π 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.
π 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.