This system explores utilizing:
- Animation with CSS
transition
andrework
- 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-within
– for 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:
aria-label
on the<nav>
to assist establish it is function when assistive tech is used to navigate a web page by landmarks- Use of a
button
as a focusable, discoverable factor to set off the opening of the dropdown aria-controls
on the.dropdown__title
that hyperlinks to the id of the.dropdown__menu
to affiliate it with the menu for assistive techaria-expanded
on thebutton
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:
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;
}
}
}
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:
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;
}
}
}
}
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;
}
}
}
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:
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.
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:
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:
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);
}
}
}
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)