2nd Aug 2022
4 mins

Web Navigation: A bit more reponsiv-al and accessible

#html5#accessiblity#responsive

Recently i started revamping my personal portfolio, and while doing that I came up with two of many practices that helps a website to become a lot better. These two practices are Responsiveness and Accessibility. Even though these practices are not new but for some reason I was running away from fully understanding these. So leaving my procrastination aside I jumped into learning these things and decided that from now on I will pay complete attention to build all my future web projects considering these two practices.

To keep things short in this article I will build a website header navigation which is both responsive as well as follow accessibility practices.

(Please note that this is the first time I am trying to understand and implement accessibility apis, so if I miss out anything please feel free to correct me 😬😬).

So lets jump into it -

So one thing that I learned on accessible apis is that if available we should always follow HTML5 semantics and for elements where we HTML5 semantics are not enough we can go with ARIA. So for our navigation we will start with a <header> element

<header class="header">
  <span class="logo">...logo icon...</span>
  <button class="nav-toggle" type="button" aria-controls="navigation" aria-expanded="false">
  ..open and close icons...
  <span class="sr-only">Menu</span>
  </button>
  <nav>
    <ul id="navigation" class="navigation" data-visible="false">
      <li class="navlink"><a href="#section-1">Section 1</a></li>
      <li class="navlink"><a href="#section-2">Section 2</a></li>
      <li class="navlink"><a href="#section-3">Section 3</a></li>
      <li class="navlink"><a href="#section-4">Section 4</a></li>
    </ul>
  </nav>
</header>
HTML code

To make our navigation we will use <nav> element which is by HTML semantic definition can be used for site navigation also it helps screen readers to identify the a section as navigation.

Also you would see that I have added an attribute called data-visible to the <ul> which is used to make it Responsive by hiding the navigation on mobile devices  initially. Also since the navigation is hidden we need button to make it appear for that we are using a nav-toggle button. This button actually contains few other attributes such as -

  • type="button" Tells the browser exact type for this element,
  • aria-controls="#id of element" tells screen reader that what section this button controls, also some screen reader can provide a shortcut to jump to given section
  • aria-expanded="false | true" for telling the screen reader whether the controlled section is hidden(collapsed) or visible(expanded).

One more thing to notice is when we are using icon only in the button, screen readers can not understand the purpose of the button for that we can supply a text which will can make only available to screen readers using css, here we have used <span class="sr-only">. And this sr-only rule look like -

.sr-only{
  clip: rect(0 0 0 0); 
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap; 
  width: 1px;
}
CSS to make text available to screen readers only

Once this is done we can move on to making it responsive with the help of CSS. For that we will change style of our navigation and hide it (by setting its opacity to 0)

.navigation {
    position: fixed;
    inset: 0 0;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background: #f5f5f5;
    opacity: 0; /* <-- here   */
    transition: opacity 0.3s ease;
  }
setting navigation opacity to 0

on small screen and at its place we will show a hamburger icon which will help us to show the navigation on click. To show the navigation we will use javascript -

const navigation = document.querySelector(".navigation");
const navToggle = document.querySelector(".nav-toggle");
const menuIcon = document.querySelector("#menu");
const closeIcon = document.querySelector("#close");

navToggle.addEventListener("click", () => {
  const navVisible = navigation.getAttribute("data-visible");
  console.log("clicked", navVisible);
  if (navVisible == "true") {
    navigation.setAttribute("data-visible", false);
    menuIcon.setAttribute("data-visible", true);
    closeIcon.setAttribute("data-visible", false);
    navToggle.setAttribute("aria-expanded", false);
  } else if (navVisible == "false") {
    navigation.setAttribute("data-visible", true);
    menuIcon.setAttribute("data-visible", false);
    closeIcon.setAttribute("data-visible", true);
    navToggle.setAttribute("aria-expanded", true);
  }
});
hiding and showing navigation using js

Here we added an event listener on click of hamburger button and we will toggle the value of data-visible attribute of navigation. In CSS we have written a rule based on navigation's data-visible attribute -

 .navigation[data-visible="true"] {
    opacity: 1;
  }
setting navigation opacity to 1

by setting the opacity to 1 our navigation will start showing up on the screen, and once the data-visible becomes false it will hide again. Also we will show and hide menu and close icons based on the same condition. One more thing we need to take care here is setting up the aria-expanded to its correct value for the screen reader, that can also be done here using same condition block.

And that is all for making our website's Navigation a responsive and bit more accessible. I know above explanation could feel very abstract and disconnected, for that below is the Codepen of working solution.

https://codepen.io/as-ajitsingh/pen/PoREVdP

At the end I would really like to thank Kevin Powell's Responsive navbar tutorial using HTML CSS & JS video for making me easily understand this concept and ARIA, Accessibility APIs and coding like you give a damn! – Léonie Watson / Front-Trends 2015 for getting me interested into accessible web development.  Also I used https://developer.mozilla.org/ for quickly understanding and resolving doubts for various web concepts.

Cover Photo by Aris Munandar on Unsplash.