Master Etch with tutorials, tips, and tricks.

Search

Recent articles

Additional Code for WP Menus

  • CSS
  • JavaScript
  • Menus

Zack Pyle released a really nice plugin to re-enable the native menu management system. It produces an easy-to-use loop function but leaves the styling and JS functionality to you. Here are the basics for a dropdown to work correctly.

Note: This assumes you are just using Zacks’ sample code.

JavaScript

document.addEventListener('DOMContentLoaded', () => {
  document.querySelectorAll('.site-nav').forEach((nav) => {
    const triggers = nav.querySelectorAll('.site-nav__dropdown-trigger');

    const closeDropdown = (trigger) => {
      const submenuId = trigger.getAttribute('aria-controls');
      const submenu = submenuId ? document.getElementById(submenuId) : null;

      trigger.setAttribute('aria-expanded', 'false');

      if (submenu) {
        submenu.classList.remove('is-open');
      }
    };

    const openDropdown = (trigger) => {
      const submenuId = trigger.getAttribute('aria-controls');
      const submenu = submenuId ? document.getElementById(submenuId) : null;

      trigger.setAttribute('aria-expanded', 'true');

      if (submenu) {
        submenu.classList.add('is-open');
      }
    };

    const closeAllDropdowns = (exceptTrigger = null) => {
      triggers.forEach((trigger) => {
        if (trigger !== exceptTrigger) {
          closeDropdown(trigger);
        }
      });
    };

    triggers.forEach((trigger) => {
      trigger.addEventListener('click', () => {
        const isExpanded = trigger.getAttribute('aria-expanded') === 'true';

        closeAllDropdowns(trigger);

        if (isExpanded) {
          closeDropdown(trigger);
        } else {
          openDropdown(trigger);
        }
      });

      trigger.addEventListener('keydown', (event) => {
        if (event.key === 'Escape') {
          closeDropdown(trigger);
          trigger.focus();
        }
      });
    });

    nav.addEventListener('keydown', (event) => {
      if (event.key === 'Escape') {
        closeAllDropdowns();
      }
    });

    document.addEventListener('click', (event) => {
      if (!nav.contains(event.target)) {
        closeAllDropdowns();
      }
    });
  });
});

CSS

.site-nav {
  display: flex;
  flex-direction: column;
  gap: var(--card-gap);
  padding: var(--space-xs);

  & .site-nav__dropdown {
    opacity: 0;
    transform: translateY(-0.5rem);
    display: none;

    transition:
      opacity 0.2s ease-in,
      transform 0.2s ease-in,
      display 0.2s allow-discrete;
  }

  & .site-nav__dropdown.is-open {
    display: flex;
    opacity: 1;
    transform: translateY(0);
    flex-direction: column;

    @starting-style {
      opacity: 0;
      transform: translateY(-0.5rem);
    }
  }

  & .site-nav__dropdown-trigger[aria-expanded='true'] .site-nav__chevron {
    rotate: 180deg;
  }
}

Share Your Thoughts

Your email address will not be published. Required fields are marked *