This is a premium alert message you can set from Layout! Get Now!

Making dropdown menus with CSS for your apps

0

A dropdown menu makes it easy for users to navigate web applications and sites. With CSS, we can create an amazing, responsive, accessible dropdown menu for both keyboard and mouse users.

The CSS dropdown approach in this lesson uses:

  1. The :focus-within pseudo-class to activate the dropdown items
  2. An input checkbox to toggle the main dropdown on smaller screens
  3. Semantic HTML elements and ARIA attributes to assist screen readers

While these techniques do not require JavaScript, you can improve their implementation with JavaScript, especially for screen reader users.

We will cover the following in this lesson:

A preview of our dropdown with CSS project

At the end of this lesson, we will have a responsive dropdown menu with CSS that looks like so:

Simple Example Site Header With Space For Logo And Three Main Menu Items. User's Mouse Shown Hovering Over Menu Items With Second Menu Item Displaying Dropdown Of Three Sub-Items

You can interact with the project on CodePen to see our final project in action. After that, let’s get started!

Building an accessible dropdown menu with CSS begins by using semantic HTML5 markup and structuring the menu to guide users to their destination.

The code below sets up some simple navigation with three primary menu items — Home, Services, and About. The Services item contains a dropdown with three nested ul submenu items:

<header>
  <div class="header-content">

    <a href="#" class="logo">Logo</a>

    <input type="checkbox" id="hamburger">
    <label for="hamburger"><span></span></label>

    <nav>
      <ul class="menus">
        <li><a href="#">Home</a></li>
        <li>
          <button type="button">Services</button>
          <ul class="dropdown">
            <li><a href="#">Web design</a></li>
            <li><a href="#">Web dev</a></li>
            <li><a href="#">Web</a></li>
          </ul>
        </li>
        <li><a href="#">About</a></li>
      </ul>
    </nav>
  </div>
</header>

By using unordered list items, screen readers will know how many links are in the navigation. The output should look like so:

Plain Menu Created With Html Displaying Unordered List Of Three Main Items And Three Sub Items Under Second Main Item

The checkbox included in the code and as seen in the image will be used to toggle the main dropdown on smaller screens.

Mobile-first dropdown menu design with CSS

We’ll start by styling the navigation for smaller screens. In the CSS file, we’ll add the following styles:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: sans-serif;
}

header {
  position: relative;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.07), 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}

.header-content {
  align-items: center;
  max-width: 1200px;
  margin: 0 auto;
  padding: 10px 20px;
  color: #212529;
}

.logo {
  text-decoration: none;
  font-size: 25px;
  color: inherit;
  margin-right: 20px;
}

label {
  padding: 23px 20px;
  position: absolute;
  cursor: pointer;
  right: 0;
  top: 0;
}

input[type="checkbox"] {
  opacity: 0;
  position: absolute;
  right: 0;
}

label span {
  width: 20px;
  height: 3px;
  display: block;
  background: #4f3e3e;
  position: relative;
}

label span::after, label span::before {
  content: "";
  position: absolute;
  display: block;
  background: inherit;
  width: inherit;
  height: inherit;
}

label span::before{
  top: 8px;
}

label span::after {
  bottom: 8px;
}

label::before {
  position: absolute;
  content: "";
  width: 58px;
  height: 49px;
  top: 0;
  right: 0;
}

input[type="checkbox"]:focus + label::before {
  box-shadow: 0 0 20px black;
}

ul {
  background: #f2f2f2;
}

ul li {
   list-style: none;
   font-size: 18px;
}

ul li button {
    font-size: inherit;
    border: none;
    background-color: transparent;
    cursor: pointer;
    width: 100%;
}

ul li a {
   display: block;
   color: inherit;
   text-decoration: none;
}

ul li a, ul li button {
  padding: 0.7rem 1rem;
  text-align: left;
}

.menus {
  position: absolute;
  top: 3.2rem;
  left: 0;
  right: 0;
}

.dropdown {
  padding: 2px 1.5rem;
}

Now we should have a dropdown menu that looks like so:

Simple Menu With Basic Css Styling Displaying Three Main Items And Three Subitems Under Second Main Item In Vertical Unordered List

Let’s get into the code in the next section.

What is happening in the CSS?

Using the CSS position: absolute; on the .menus class selector, we placed the navigation dropdown relative to the header bar, as seen in the image above.

After that, we used the ::before and ::after pseudo-class to transform the input checkbox into a custom hamburger menu to activate a dropdown on smaller screens.

Be aware that we used opacity: 0; to hide the input checkbox instead of a display: none; property:

input[type="checkbox"] {
  opacity: 0;
  /* ... */
}

Meanwhile, with the code below, the hamburger icon can receive a focus when a keyboard user navigates via the tab key:

input[type="checkbox"]:focus + label::before {
  box-shadow: 0 0 20px black;
}

Toggling the dropdown block

Allowing users to toggle the dropdown menu can greatly enhance the UX — especially on smaller mobile screens, where an always-visible menu would obscure most or all of the viewport.

We will first hide the dropdown using the CSS visibility property:

.menus {
  /* ... */
  /* hide dropdown on small screens */
  visibility: hidden;
}

Then, toggle the dropdown when the hamburger is clicked:

/* toggle main dropdown */

input[type="checkbox"]:checked ~ nav > ul {
  visibility: visible;
}

The CSS rule above targets the dropdown ul dropdown that is a direct child to the nav element following the input checkbox. The behavior should look like so:

User's Mouse Shown Hovering Over Hamburger Button Which Toggles Menu Display On And Off Each Time It Is Clicked

Using the :focus-within pseudo-class

We will use the CSS :focus-within to activate the Services dropdown items when the Services menu item receives a focus or is being clicked.

Let’s update the .dropdown class selector to hide the Services dropdown items:

.dropdown {
  /* ... */
  height: 0;
  overflow: hidden;
}

Then, add this rule to active the dropdown:

li:focus-within .dropdown {
  height: 135px;
}

The CSS rule above matches the dropdown if the parent li element is focused. In other words, the submenu will display if we click on the Services item or focus on it via the tab key.

Adding a dropdown indicator

We’ll add a dropdown arrow to the Services item to indicate that a dropdown exists. Let’s update the Services item to include a span element with an arrow class name:

<li>
  <button type="button">Services <span class="arrow"></span></button>
  <ul class="dropdown">
    <!-- ... -->
  </ul>
</li>

In the CSS, we will add a style rule for the class selector:

.arrow {
  width: 0.5em;
  height: 0.5em;
  display: inline-block;
  vertical-align: middle;
  border-left: 0.15em solid currentColor;
  border-bottom: 0.15em solid currentColor;
  transform: rotate(-45deg);
  margin-left: 0.38em;
  margin-top: -0.25em;
}

If we save, we should have the arrow placed next to the Services menu item, like so:

Same Menu As Before But Now Shown With Dropdown Arrow Indicator Next To Second Main Item And Collapsed Sub-Item List

To rotate the arrow upward when the dropdown is opened, we will add the following CSS rule:

li:focus-within > button > .arrow {
  transform: rotate(-225deg);
  margin-top: 4px;
}

Implementing a transition to the dropdown

We’ll add a smooth transition effect for when the user opens or closes the dropdown menu. Starting with the main dropdown menu, we’ll update the .menus to include transform and transition CSS properties:

.menus {
  /* ... */
  /* smooth transitioning */
  transform: translateY(-1em);
  transition: transform ease 0.2s;
}

Then, when the dropdown is active, we will use the transform CSS property to move the dropdown back to its original position:

input[type="checkbox"]:checked ~ nav > ul {
  /* ... */
  transform: translateY(0);
}

Next, we will add a transition to the Services dropdown and its arrow indicator. Let’s update the .dropdown to transition the height property like so:

.dropdown {
  /* ... */
  transition: height ease 0.2s;
}

Then, for the arrow, we’ll transition the transform property so we have the following:

.arrow {
  /* ... */
  transition: transform 100ms ease-in-out;
}

If we save the CSS, the dropdown should behave like so:

User's Mouse Shown Clicking On Hamburger Button To Toggle Menu On And Then Clicking Dropdown Arrow Button To Open Sub-Item List Under Services

Enhancing CSS dropdown menu for screen readers

Adding ARIA attributes to the dropdown will help screen readers convey the intended behavior and purpose for visually impaired users.

We’ll add an aria-label attribute to interactive elements so that screen reader software can announce the purpose of the control while navigating through the dropdown menu. Meanwhile, the aria-haspopup attribute will inform screen readers that there is a popup.

The aria-controls attribute will map the controlling element to the expanded widget. We’ll set the id of the expanded widget to the value of the aria-controls attribute on the controlling element.

Finally, aria-expanded will tell the screen reader if a dropdown is presently hidden or not. It needs to toggle between true or false depending on the state of the dropdown. This is one place we can improve the dropdown accessibility with JavaScript.

With our CSS implementation, the :focus-within pseudo-class will immediately open the dropdown when visually impaired users move the focus to the dropdown item. For this, by assigning a Boolean value of true to the aria-expanded, the screen reader’s software will interpret the dropdown widget correctly.

We can install the Chrome extension Screen Reader to observe the interpretation.

Let’s update the HTML markup to include the ARIA attributes:

<header>
 <div class="header-content">
  <!--... -->
  <input type="checkbox" id="hamburger" aria-label="menu button">
  <label for="hamburger"><span></span></label>

  <nav aria-label="main navigation">
   <ul class="menus">
    <!-- ...-->
    <li>
     <button 
      type="button" 
      aria-haspopup="true" 
      aria-expanded="true" 
      aria-controls="dropdown1"
     >
      Services<span class="arrow"></span>  
     </button>
     <ul class="dropdown" id="dropdown1">
      <!--... -->
     </ul>
    </li>
    <!--... -->
   </ul>
  </nav>
 </div>
</header>

If we use the keyboard to navigate the dropdown, the behavior will look like so:

User's Mouse Shown Not Moving To Demonstrate Use Of Keyboard To Toggle Hamburger Button And Dropdown Arrow

As we can see, once we move the focus to the Services item, the dropdown opens immediately. Thus, the screen reader will correctly announce the expansion.

Designing dropdown menus for larger screens with CSS

We will use the CSS media queries and define the style rules for a screen width of 640px and above:

/* MEDIA QUERIES */
@media (min-width: 640px) {

 .header-content {
  display: flex;
 }

 .menus {
  position: static;
  visibility: visible;
  background: #fff;
  display: flex;
  transform: initial;
 }

 label, input[type="checkbox"] {
  display: none;
 }

 ul li {
  position: relative;
  font-size: 14px;
 }

 ul li a:hover,
 ul li button:hover {
  background-color: #f2f2f2;
 }

 .dropdown {
  position: absolute;
  right: 0;
  left: auto;
  box-shadow: 0 10px 15px -3px rgba(46, 41, 51, 0.08),
  0 4px 6px -2px rgba(71, 63, 79, 0.16);
  z-index: 99;
  min-width: 10rem;
  padding: 0;
  background-color: #fff;
  border-radius: 0 0 0.5rem 0.5rem; 
 }

 ul li:hover .dropdown {
  height: 135px;
 }

 ul li:hover > button > .arrow {
  transform: rotate(-225deg);
  margin-top: 4px;
 }
}

In the above CSS, we started by adding a display: flex; to the header content to position the logo, and navigation menus side-by-side. After, we added a position: static; declaration on the navigation content to override the absolute positioning we used for mobile design and place the nav items in the normal flow of the page.

It is also important to note how we included rules to activate the dropdown on hover with the :hover pseudo-class. The result now looks like so:

Same Menu Items Displayed But In Horizontal Format Instead Of Vertical Unordered List To Demonstrate Dropdown Behavior For Larger Screens

Accessibility support for the Safari browser

By default, using the tab key for navigation is disabled in Safari. We can enable it by opening our Safari Preferences and opening our Advanced settings. Then, in the Accessibility section, we can check the checkbox labeled “Press Tab to highlight each item on a webpage.”

We may also notice that clicking on the Services menu item does not show a dropdown in Safari. An element on Safari will get a :focus-within if it has a tabindex="0". So, we will update the li for Services to include a tabindex:

<li tabindex="0">
  <button 
    <!--  ...   -->
  >
    Services<span class="arrow"></span>   
  </button>
  <ul class="dropdown" id="dropdown1">
    <!--  ... -->
  </ul>
</li>

The dropdown should now work as expected.

Conclusion

Creating a fantastic dropdown menu is possible with CSS, as shown in this lesson. The dropdown is accessible by keyboard, mouse, and screen-reader users. We can further improve on CSS dropdown menus using a scripting language like JavaScript.

Dropdown menus are a common design pattern in modern apps. To learn more about them, you can look at building a multilevel dropdown menu in React.

If you have questions or contributions, please share your thought in the comment section. Finally, endeavor to share this lesson around the web.

The post Making dropdown menus with CSS for your apps appeared first on LogRocket Blog.



from LogRocket Blog https://ift.tt/io7lrZv
Gain $200 in a week
via Read more

Post a Comment

0 Comments
* Please Don't Spam Here. All the Comments are Reviewed by Admin.
Post a Comment

Search This Blog

To Top