Saturday, May 18, 2024
HomeCSSCSS-Solely Accessible Dropdown Navigation Menu

CSS-Solely Accessible Dropdown Navigation Menu


This system explores utilizing:

  • Animation with CSS transition and rework
  • Utilizing the :focus-within pseudo-class
  • CSS grid for positioning
  • dynamic centering method
  • Accessibility concerns for dropdown menus

For those who’ve ever pulled your hair out coping with the idea of “hover intent”, then this improve is for you!

Earlier than we get too far, whereas our method 100% makes use of solely CSS, there’s a want so as to add some Javascript for a extra comprehensively accessible expertise. There’s additionally a polyfill wanted for a key characteristic to make this work – :focus-withinfor probably the most dependable assist. However we have nonetheless drastically improved from the times of needing a number of jQuery plugins to perform the visible results.

Accessibility replace – 08/18/20: An enormous due to Michael Fairchild of Deque (and creator of the wonderful useful resource a11ysupport.io) for testing the unique resolution throughout numerous assistive know-how. The CSS-only methodology wants some Javascript to totally meet WCAG 2.1. Particularly, javascript must be used to supply a non-mouse/non-tab approach to dismiss the menu (assume escape key) to satisfy success standards 1.4.13. Michael pointed to this WAI-ARIA Authoring Practices demo which gives extra data on the required Javascript options. These are extremely advisable additions in your last manufacturing resolution.


For those who’ve not used Sass, it’s possible you’ll wish to take 5 minutes to know the nesting syntax of Sass to most simply perceive the code samples given.

We are going to improve this as we proceed, however here is our beginning construction:

<nav aria-label="Essential Navigation">
<ul>
<li><a href="#">About</a></li>
<li class="dropdown">
<button
sort="button"
class="dropdown__title"
aria-expanded="false"
aria-controls="sweets-dropdown"
>

Sweets
</button>
<ul class="dropdown__menu" id="sweets-dropdown">
<li><a href="#">Donuts</a></li>
<li><a href="#">Cupcakes</a></li>
<li><a href="#">Chocolate</a></li>
<li><a href="#">Bonbons</a></li>
</ul>
</li>
<li><a href="#">Order</a></li>
</ul>
</nav>

Overlooking the button for a minute, that is the semantic commonplace for navigation hyperlinks. This construction is versatile to stay anyplace in your web page, so it might be a desk of contents in your sidebar as simply as it’s the major navigation.

Proper out the gate, we’ve got applied a couple of options particularly for accessibility:

  1. aria-label on the <nav> to assist establish it is function when assistive tech is used to navigate a web page by landmarks
  2. Use of a button as a focusable, discoverable factor to set off the opening of the dropdown
  3. aria-controls on the .dropdown__title that hyperlinks to the id of the .dropdown__menu to affiliate it with the menu for assistive tech
  4. aria-expanded on the button which in your last resolution wants toggled by way of Javascript as famous within the demo talked about originally of this text

As famous by Michael, use of a button factor additionally permits Dragon Naturally Talking customers to say one thing like ‘click on button’ to open the menu.

Our (largely) default beginning look is as follows:

default list of links

Preliminary Navigation Kinds

First, we’ll give some container types to nav and outline it as a grid container. Then we’ll take away default record types from the nav ul and nav ul li.

nav {
background-color: #eee;
padding: 0 1rem;
show: grid;
place-items: middle;

ul {
list-style: none;
margin: 0;
padding: 0;
show: grid;

li {
padding: 0;
}
}
}

navigation list with list styles removed

We have misplaced the hierarchical definition, however we will start to carry it again with the next:

nav {

> ul {
grid-auto-flow: column;

> li {
margin: 0 0.5rem;
}
}
}

Through the use of the kid combinator selector > we have outlined that the top-level ul which is a direct youngster of nav ought to swap it is grid-auto-flow to column which successfully updates it to be alongside the x-axis. We then add margin to the top-level li components for a bit extra definition. Now, the longer term dropdown gadgets are showing contained beneath the “Sweets” menu and are extra clearly its youngsters:

nav list with direct child styles

Subsequent we’ll add a contact of fashion first to all hyperlinks in addition to the .dropdown__title, then to solely the top-level hyperlinks along with the .dropdown__title. That is additionally the place we filter the native browser types inherited for button components.


.dropdown__title {
background-color: clear;
border: none;
font-family: inherit;
}

nav {
> ul {
> li {
a,
.dropdown__title
{
text-decoration: none;
text-align: middle;
show: inline-block;
coloration: blue;
font-size: 1.125rem;
}


> a,
.dropdown__title
{
padding: 1rem 0.5rem;
}
}
}
}

updated link styles

We’ve to this point been counting on factor selectors, however we are going to carry at school selectors for the dropdown since there could also be a number of in a given navigation record.

We’ll first fashion up the .dropdown__menu and its hyperlinks to assist establish it extra clearly as we work by positioning and animation:

.dropdown {
place: relative;

.dropdown__menu {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 0.15em 0.25em rgba(black, 0.25);
padding: 0.5em 0;
min-width: 15ch;

a {
coloration: #444;
show: block;
padding: 0.5em;
}
}
}

dropdown__menu styles

One of many clear points is that the .dropdown__menu is affecting the nav container, which you’ll be able to see from the gray nav background being current across the dropdown.

We will begin to repair this by including place: absolute to the .dropdown__menu which takes it out of regular doc circulation:

menu with position absolute

You may see it is aligned to the left and beneath of the dad or mum record merchandise. Relying in your design, this can be the fascinating location.

We’ll pull out a centering trick to align the menu central to the record merchandise:

.dropdown__menu {

place: absolute;


high: calc(100% - 0.25rem);
left: 50%;
rework: translateX(-50%);
}

The magic of this centering method is that the menu might be any width or perhaps a dynamic width and it will middle appropriately.

centered dropdown__menu styles

There are two main triggers we wish used to open the menu: :hover and :focus.

Nevertheless, conventional :focus won’t persist the open state of the dropdown. As soon as the preliminary set off loses focus, the keyboard focus should transfer by the dropdown menu, however visually the menu would disappear.

There’s an upcoming pseudo-class known as :focus-within and it’s exactly what we have to make it potential for this to be a CSS-only dropdown. As talked about within the intro, it does require a polyfill if it is advisable to assist IE < Edge 79 (you do… for now).

From MDN, italics mine to indicate the half we’ll profit from:

The :focus-within CSS pseudo-class represents a component that has obtained focus or comprises a component that has obtained focus. In different phrases, it represents a component that’s itself matched by the :focus pseudo-class or has a descendant that’s matched by :focus.

Conceal the dropdown by default

Earlier than we will reveal the dropdown, we have to cover it, so we are going to use the hidden types because the default state.

Your first intuition could also be show: none however that locks us out of gracefully animating the transition.

Subsequent, you would possibly strive merely opacity: 0 which visibly hides it however leaves behind “ghost hyperlinks” as a result of the factor nonetheless has computed peak.

As an alternative, we are going to use a mixture of opacity, rework, and visibilty:

.dropdown__menu {
rework: rotateX(-90deg) translateX(-50%);
transform-origin: high middle;
opacity: 0.3;
}

We add opacity however not all the way in which to 0 to allow a bit smoother impact later.

And, we replace our rework property to incorporate rotateX(-90deg), which can rotate the menu in 3D house to 90 levels “backwards”. This successfully removes the peak and can make for an fascinating transition on reveal. Additionally you will discover the transform-origin property which we add to replace the purpose round which the rework is utilized, versus the default of the horizontal and vertical middle.

Moreover, to satisfy success standards 1.3.2, the hyperlinks ought to be hidden from display screen reader customers till they’re visually displayed. We guarantee this habits by together with visibility: hidden (thanks once more to Michael for this tip!).

Earlier than we do the reveal, we have to add a transition property. We add it to the primary .dropdown__menu rule in order that it applies each on and off focus/hover, aka “forwards” and “backwards”.

.dropdown__menu {
transition: 280ms all ease-out;
}

With all that prior setup, revealing the dropdown on each hover and focus will be achieved as succinctly as:

.dropdown {

&:hover,
&:focus-within
{
.dropdown__menu {
opacity: 1;
rework: rotateX(0) translateX(-50%);
visibility: seen;
}
}
}

First, we reverse the visibilty (or the opposite properties wouldn’t work), after which we have reversed the rotateX by resetting to 0, after which carry the opacity all the way in which as much as 1 for full visibility.

This is the outcome:

demo of reveal on focus and hover

The rotateX property permits the looks of the menu swinging in from the again, and opacity simply makes it just a little softer transition total.

As soon as once more a be aware that for full accessibility, there’s a want for Javascript to totally deal with for keyboard assistive tech occasions that don’t all the time set off :focus. This implies some sighted keyboard customers could uncover the dropdown hyperlinks, however and not using a :focus occasion emitted, they won’t see the dropdown menu really open. Assessment the w3c demo for learn how to end incorporating Javascript on this resolution.

For those who’ve been at this internet factor for some time, I am hoping the next will make you go 🤯

After I first started battling dropdown menus I used to be creating them primarily for IE7. On an enormous venture, a number of crew members requested one thing alongside the strains of “are you able to cease the menu showing if I am simply scrolling/mousing over the menu?”. The answer I lastly discovered after a lot Googling (together with making an attempt to give you the correct phrase to get what I used to be after) was the hoverIntent jQuery plugin.

I wanted to set that up as a result of since we’re utilizing the transition property, we will additionally add a really slight delay. For normal functions, it will forestall the dropdown animation triggering for “drive-by” mouseovers.

Order issues after we’re defining all transition properties in a single line, and the second numerical worth so as can be picked up because the delay worth:

.dropdown__menu {
// ... current types
transition: 280ms all 120ms ease-out;
}

Take a look at the outcomes:

demo of transition delay with mouseover

It takes a reasonably leisurely rollover to set off the menu, which we will loosely infer as intent to open the menu. The delay remains to be quick sufficient to not be consciously observed previous to opening the menu, so it is a win!

You should still select to make use of Javascript to boost this significantly if it is going to launch a “mega menu” that will be extra disruptive, however that is nonetheless fairly pleasant.

Hover intent is one factor, however actually we want an extra cue to the person that this menu has extra choices. An especially frequent conference is a “caret” or “down arrow” mimicking the indicator of a local choose factor.

So as to add this, we are going to replace the .dropdown__title types. We’ll outline it as an inline-flex container after which create an :after factor that makes use of the border trick to create a downward arrow. We use a splash of translateY() to optically align it with our textual content:

.dropdown {

.dropdown__title {
show: inline-flex;
align-items: middle;

&:after {
content material: "";
border: 0.35rem strong clear;
border-top-color: rgba(blue, 0.45);
margin-left: 0.25em;
rework: translateY(0.15em);
}
}
}

dropdown caret indicator

This is one other place the place in the end you will have to boost with Javascript.

To maintain it CSS-only, and acceptable for non-application web sites, it is advisable to apply tabindex="-1" on the physique, successfully permitting any clicks outdoors of the menu to take away focus from it and permitting it to shut.

This can be a little bit of a stretch – and it might be just a little irritating to customers – so it’s possible you’ll wish to improve this to cover on scroll as effectively with Javascript particularly in the event you outline the nav to make use of place: sticky and scroll with the person.

This is the ultimate outcome with a bit of additional styling together with an arrow to extra visually join the menu to the hyperlink merchandise, customized focus states on all of the nav hyperlinks, and place: sticky on the nav:

By Stephanie Eckles (@5t3ph)



RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments