Monday, August 8, 2016

Completing Our Draggable Off-Canvas Menu with GreenSock_part1

What You'll Be Creating
In the first part of this Draggable journey, we discussed how to include scripts, investigated the ThrowPropsPlugin, including the requirements to jump start our project in hopes of taking it to eleven! Now, get ready to make an off-canvas menu system which reacts to keyboard and touch.

The Demo
The full demo that we’ll be building and discussing for the remainder of this tutorial is also available on CodePen.

I encourage you to test this for yourself across as many devices as possible, especially keyboard navigation. Each interaction–whether touch, keyboard or mouse–has been accounted for, but as you’ll find in our current landscape you can’t detect a touchscreen and at times trying to do so even results in false positives.

The Setup

Using the markup from part I we’ll begin by adding a container div for structural purposes along with correlating classes for CSS and JavaScript hooks.
  1. <div class="app">
  2.   <header class="dragaebel-lcontainer" role="banner">
  3.     <a href="/" class="js-draglogo">…</a>
  4.     <a href="#menu" class="dragaebel-toggle js-dragtoggle" id="menu-button">…</a>
  5.     <nav class="dragaebel-nav js-dragnav" id="menu" role="navigation">…</nav>
  6.   </header>
  7.   <main role="main">
  8.     <div class="dragaebel-lcontainer js-dragsurface"></div>
  9.   </main>
  10. </div>
Classes that begin with the ”js” prefix signify that these classes only appear in JavaScript; removing them would hinder functionality. They’re never used in CSS, helping to isolate the focus of concerns. The surrounding container will help to control scrolling behavior which is discussed in the upcoming CSS section.

Accessibility

With the the foundation in place it’s time to add a layer of ARIA on top to lend semantic meaning to screen readers and keyboard users.
  1. <nav aria-hidden="true">…</nav>
Since the menu will be hidden by default the aria-hidden attribute is labeled true and will be updated accordingly depending on the menu’s state; false for open, true for closed. Here’s an explanation of the attribute aria-hidden per the W3C specification:
Indicates that the element and all of its descendants are not visible or perceivable to any user as implemented by the author. […] Authors MUST set aria-hidden=”true” on content that is not displayed, regardless of the mechanism used to hide it. This allows assistive technologies or user agents to properly skip hidden elements in the document. ~W3C WAI-ARIA Spec
Authors should be careful what content they hide, making this attribute a separate discussion outside the scope of this article. For those curious, the specification defines the attribute in further length and is somewhat grokkable; something I don’t usually say that often about specification jargon.

The CSS

Our CSS is where the magic really begins. Let’s take the important parts from the demo that bear meaning and break it down.
  1. body {
  2.   // scroll fix
  3.   height: 100%;
  4.   overflow: hidden;
  5.   // end scroll fix
  6. }
  7. .app {
  8.   // scroll fix
  9.   overflow-y: scroll;
  10.   height: 100vh;
  11.   // end scroll fix
  12. }
  13. .dragaebel-nav {
  14.   height: 100vh;
  15.   overflow-y: auto;
  16.   position: fixed;
  17.   top: 0;
  18.   right: 0;
  19. }
Setting the body height to 100% allows the container to stretch the entire viewport, but it’s also playing a more important part; allowing us to hide its overflow.

The overflow scroll fix helps to control how the primary container and navigation behave when either one contains overflowing content. For example, If the container is scrolled—or the menu—the other will not scroll when the user reaches the end of the intially scrolled element. It’s a weird behavior, not typically discussed, but makes for a better user experience.

Viewport Units

Viewport units are really powerful and play a vital role in how the primary container holds overflowing content. Viewport units have wonderful support across browsers these days and I highly suggest you start using them. I’ve used vh units on the nav, but I could have used a percentage instead. During development it was discovered that div.app must use vh units since percentage won’t allow for the overflowing content to maintain typical scrolling behavior; the content results in being clipped. Overflow is set to scroll in preparation in case the menu items exceeed the height of the menu or the height of the viewport becomes narrow.
  1. // Allow nav to open when JS fails
  2. .no-js .dragaebel-nav:target {
  3.   margin-right: 0;
  4. }
  5. .dragaebel-nav {
  6.   margin-right: -180px;
  7.   width: 180px;
  8. }
The .no-js .nav:target provides access to our menu regardless if JavaScript fails or is turned off, hence the reason we added the ID value to the href attribute of the menu trigger.

The primary navigation is moved to the right via a negative margin which is also the same as the nav’s width. For the sake of brevity I’m writing Vanilla CSS, but I’m sure you could write something fancier in a pre-processor of your choice.
Written by Dennis Gaebel

If you found this post interesting, follow and support us.
Suggest for you:

JavaScript for Absolute Beginners

JavaScript For Beginners - Learn JavaScript From Scratch

JavaScript for Beginners

JavaScript Bootcamp - 2016

ES6 Javascript: The Complete Developer's Guide

No comments:

Post a Comment