Search code examples
htmlcsspure-css

Why my Pure.css submenu is not showing on click?


According to the Pure.css documentation, a dropdown menu should appear when I click on Option3, but it doesn't. Why is it?

.custom-restricted-width {
  width: 150px;
}
<link href="https://unpkg.com/purecss@0.6.1/build/pure-min.css" rel="stylesheet" />
<div id="menu">
  <div class="pure-menu custom-restricted-width">
    <a class="pure-menu-heading" href="index.html">Title</a>
    <ul class="pure-menu-list">
      <li class="pure-menu-item"><a href="#" class="pure-menu-link">Mune item 1</a>
      </li>
      <li class="pure-menu-item pure-menu-has-children">
        <a href="#" id="menuLink1" class="pure-menu-link">Menu item 2</a>
        <ul class="pure-menu-children">
          <li class="pure-menu-item"><a href="#" class="pure-menu-link">Submenu item 1</a>
          </li>
          <li class="pure-menu-item"><a href="#" class="pure-menu-link">Submenu item 2</a>
          </li>
        </ul>
      </li>
    </ul>
  </div>
</div>


Solution

  • I've found the solution after reading the document again:

    We recommend enabling submenus via JavaScript to enable accessibility. To help get you started, an example script written in vanilla JS provides ARIA support, limited submenu arrow-key navigation, and the ability to dismiss menus with an outside event or the ESC key.

    So if you download the example script above and include it with <script src="js/dropdown.js"></script> or something alike, the dropdown menu would work as expected.

    (function(window, document) {
      'use strict';
    
      // Enable drop-down menus in Pure
      // Inspired by YUI3 gallery-simple-menu by Julien LeComte
      // [https://github.com/yui/yui3-gallery/blob/master/src/gallery-simple-menu/js/simple-menu.js]
    
      function PureDropdown(dropdownParent) {
    
        var PREFIX = 'pure-',
          ACTIVE_CLASS_NAME = PREFIX + 'menu-active',
          ARIA_ROLE = 'role',
          ARIA_HIDDEN = 'aria-hidden',
          MENU_OPEN = 0,
          MENU_CLOSED = 1,
          MENU_PARENT_CLASS_NAME = 'pure-menu-has-children',
          MENU_ACTIVE_SELECTOR = '.pure-menu-active',
          MENU_LINK_SELECTOR = '.pure-menu-link',
          MENU_SELECTOR = '.pure-menu-children',
          DISMISS_EVENT = (window.hasOwnProperty &&
            window.hasOwnProperty('ontouchstart')) ?
          'touchstart' : 'mousedown',
    
          ARROW_KEYS_ENABLED = true,
    
          ddm = this; // drop down menu
    
        this._state = MENU_CLOSED;
    
        this.show = function() {
          if (this._state !== MENU_OPEN) {
            this._dropdownParent.classList.add(ACTIVE_CLASS_NAME);
            this._menu.setAttribute(ARIA_HIDDEN, false);
            this._state = MENU_OPEN;
          }
        };
    
        this.hide = function() {
          if (this._state !== MENU_CLOSED) {
            this._dropdownParent.classList.remove(ACTIVE_CLASS_NAME);
            this._menu.setAttribute(ARIA_HIDDEN, true);
            this._link.focus();
            this._state = MENU_CLOSED;
          }
        };
    
        this.toggle = function() {
          this[this._state === MENU_CLOSED ? 'show' : 'hide']();
        };
    
        this.halt = function(e) {
          e.stopPropagation();
          e.preventDefault();
        };
    
        this._dropdownParent = dropdownParent;
        this._link = this._dropdownParent.querySelector(MENU_LINK_SELECTOR);
        this._menu = this._dropdownParent.querySelector(MENU_SELECTOR);
        this._firstMenuLink = this._menu.querySelector(MENU_LINK_SELECTOR);
    
        // Set ARIA attributes
        this._link.setAttribute('aria-haspopup', 'true');
        this._menu.setAttribute(ARIA_ROLE, 'menu');
        this._menu.setAttribute('aria-labelledby', this._link.getAttribute('id'));
        this._menu.setAttribute('aria-hidden', 'true');
        [].forEach.call(
          this._menu.querySelectorAll('li'),
          function(el) {
            el.setAttribute(ARIA_ROLE, 'presentation');
          }
        );
        [].forEach.call(
          this._menu.querySelectorAll('a'),
          function(el) {
            el.setAttribute(ARIA_ROLE, 'menuitem');
          }
        );
    
        // Toggle on click
        this._link.addEventListener('click', function(e) {
          e.stopPropagation();
          e.preventDefault();
          ddm.toggle();
        });
    
        // Keyboard navigation
        document.addEventListener('keydown', function(e) {
          var currentLink,
            previousSibling,
            nextSibling,
            previousLink,
            nextLink;
    
          // if the menu isn't active, ignore
          if (ddm._state !== MENU_OPEN) {
            return;
          }
    
          // if the menu is the parent of an open, active submenu, ignore
          if (ddm._menu.querySelector(MENU_ACTIVE_SELECTOR)) {
            return;
          }
    
          currentLink = ddm._menu.querySelector(':focus');
    
          // Dismiss an open menu on ESC
          if (e.keyCode === 27) {
            /* Esc */
            ddm.halt(e);
            ddm.hide();
          }
          // Go to the next link on down arrow
          else if (ARROW_KEYS_ENABLED && e.keyCode === 40) {
            /* Down arrow */
            ddm.halt(e);
            // get the nextSibling (an LI) of the current link's LI
            nextSibling = (currentLink) ? currentLink.parentNode.nextSibling : null;
            // if the nextSibling is a text node (not an element), go to the next one
            while (nextSibling && nextSibling.nodeType !== 1) {
              nextSibling = nextSibling.nextSibling;
            }
            nextLink = (nextSibling) ? nextSibling.querySelector('.pure-menu-link') : null;
            // if there is no currently focused link, focus the first one
            if (!currentLink) {
              ddm._menu.querySelector('.pure-menu-link').focus();
            } else if (nextLink) {
              nextLink.focus();
            }
          }
          // Go to the previous link on up arrow
          else if (ARROW_KEYS_ENABLED && e.keyCode === 38) {
            /* Up arrow */
            ddm.halt(e);
            // get the currently focused link
            previousSibling = (currentLink) ? currentLink.parentNode.previousSibling : null;
            while (previousSibling && previousSibling.nodeType !== 1) {
              previousSibling = previousSibling.previousSibling;
            }
            previousLink = (previousSibling) ? previousSibling.querySelector('.pure-menu-link') : null;
            // if there is no currently focused link, focus the last link
            if (!currentLink) {
              ddm._menu.querySelector('.pure-menu-item:last-child .pure-menu-link').focus();
            }
            // else if there is a previous item, go to the previous item
            else if (previousLink) {
              previousLink.focus();
            }
          }
        });
    
        // Dismiss an open menu on outside event
        document.addEventListener(DISMISS_EVENT, function(e) {
          var target = e.target;
          if (target !== ddm._link && !ddm._menu.contains(target)) {
            ddm.hide();
            ddm._link.blur();
          }
        });
    
      }
    
      function initDropdowns() {
        var dropdownParents = document.querySelectorAll('.pure-menu-has-children');
        for (var i = 0; i < dropdownParents.length; i++) {
          var ddm = new PureDropdown(dropdownParents[i]);
        }
      }
    
      initDropdowns();
    
    }(this, this.document));
    .custom-restricted-width {
      width: 150px;
    }
    <link href="https://unpkg.com/purecss@0.6.1/build/pure-min.css" rel="stylesheet" />
    <div id="menu">
      <div class="pure-menu custom-restricted-width">
        <a class="pure-menu-heading" href="index.html">Title</a>
        <ul class="pure-menu-list">
          <li class="pure-menu-item"><a href="#" class="pure-menu-link">Mune item 1</a>
          </li>
          <li class="pure-menu-item pure-menu-has-children">
            <a href="#" id="menuLink1" class="pure-menu-link">Menu item 2</a>
            <ul class="pure-menu-children">
              <li class="pure-menu-item"><a href="#" class="pure-menu-link">Submenu item 1</a>
              </li>
              <li class="pure-menu-item"><a href="#" class="pure-menu-link">Submenu item 2</a>
              </li>
            </ul>
          </li>
        </ul>
      </div>
    </div>