☰ Mobile Menu Design Guide

Mobile hamburger menus є standard navigation pattern для responsive websites коли screen space обмежено. Named після three-line icon (☰) що resembles hamburgер, цей UI pattern reveals hidden navigation upon tap/click. Цей comprehensive guide covers UX best practices, animation patterns, accessibility considerations, та complete implementation для mushroom education website.

🎯 When to Use Hamburger Menu

✅ Good Use Cases

  • Many nav items (> 5-6): Doesn't fit horizontally
  • Secondary navigation: Not critical для immediate access
  • Mobile-only: Desktop має horizontal nav
  • Content-first sites: Article reading priority
  • Complex hierarchies: Multi-level menus

❌ Avoid If...

  • Few items (≤ 4): Tab bar кращий
  • E-commerce: visible navigation increases conversions
  • Task-critical actions: Login, cart need visibility
  • Discovery-focused: Users need browse options

📱 For Mushroom Education Website:

Recommendation: ✅ Use hamburger menu

Rationale:

  • Complex content hierarchy (Species, Safety, Growing, Therapy)
  • Mobile users primarily read articles (content-first)
  • Desktop має enough space для horizontal nav
  • Search bar needs primary position (visible)

🎨 Design Patterns

1. Icon Styles

Interactive Demo (Click to Transform):

Classic 3-Line

HTML Structure:

<button class="hamburger" aria-label="Menu" aria-expanded="false">
  <span></span>
  <span></span>
  <span></span>
</button>

CSS Animation (X Transform):

.hamburger {
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 15px;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  width: 50px;
  height: 50px;
}

.hamburger span {
  display: block;
  width: 100%;
  height: 3px;
  background: #2c3e50;
  border-radius: 3px;
  transition: all 0.3s ease;
  transform-origin: center;
}

.hamburger.active span:nth-child(1) {
  transform: rotate(45deg) translate(5px, 5px);
}

.hamburger.active span:nth-child(2) {
  opacity: 0;
}

.hamburger.active span:nth-child(3) {
  transform: rotate(-45deg) translate(7px, -6px);
}

.hamburger span:nth-child(1) { transform: translateY(-8px); }
.hamburger span:nth-child(3) { transform: translateY(8px); }

2. Menu Overlay Styles

Style Animation UX Impact Best For
Slide від Right transform: translateX(100%)translateX(0) Familiar mobile pattern Standard content sites
Slide від Left transform: translateX(-100%)translateX(0) Facebook-style drawer Apps, social platforms
Full-Screen Overlay opacity: 0opacity: 1 Immersive, focus на nav Simple menus, portfolios
Push Content Entire page slides, menu reveals Spatial awareness maintained Feature-rich apps
Expand від Top max-height: 0max-height: 100vh Simple, lightweight Minimal nav items

💻 Complete Implementation

HTML Structure:

<!-- Mobile Header -->
<header class="mobile-header">
  <!-- Logo -->
  <a href="/" class="logo">
    <img src="/logo.svg" alt="Mushroom Knowledge Hub">
  </a>
  
  <!-- Hamburger Button -->
  <button class="hamburger" 
          aria-label="Toggle navigation menu" 
          aria-expanded="false"
          aria-controls="mobile-menu">
    <span></span>
    <span></span>
    <span></span>
  </button>
</header>

<!-- Mobile Menu Overlay -->
<nav class="mobile-menu" id="mobile-menu" aria-hidden="true">
  <!-- Close Button -->
  <button class="close-menu" aria-label="Close menu">
    <svg width="24" height="24" viewBox="0 0 24 24">
      <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2"/>
    </svg>
  </button>
  
  <ul class="menu-list">
    <li><a href="/species">Mushroom Species</a></li>
    <li><a href="/effects">Effects & Science</a></li>
    <li><a href="/safety">Safety Guide</a></li>
    <li><a href="/growing">Cultivation</a></li>
    <li><a href="/microdosing">Microdosing</a></li>
    <li><a href="/therapy">Therapeutic Use</a></li>
    <li><a href="/research">Research</a></li>
    <li><a href="/community">Community</a></li>
  </ul>
  
  <!-- Optional: Secondary Links -->
  <div class="menu-footer">
    <a href="/about">About Us</a>
    <a href="/contact">Contact</a>
  </div>
</nav>

<!-- Backdrop Overlay -->
<div class="menu-backdrop"></div>

CSS Styling:

/* Mobile Header */
.mobile-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px 20px;
  background: white;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  position: sticky;
  top: 0;
  z-index: 1000;
}

/* Only show on mobile */
@media (min-width: 769px) {
  .mobile-header, .hamburger {
    display: none;
  }
}

/* Mobile Menu Overlay */
.mobile-menu {
  position: fixed;
  top: 0;
  right: 0;
  width: 85%;
  max-width: 350px;
  height: 100vh;
  background: white;
  transform: translateX(100%);
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 2000;
  overflow-y: auto;
  box-shadow: -4px 0 20px rgba(0,0,0,0.2);
}

.mobile-menu.active {
  transform: translateX(0);
}

/* Backdrop */
.menu-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.5);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s, visibility 0.3s;
  z-index: 1999;
}

.menu-backdrop.active {
  opacity: 1;
  visibility: visible;
}

/* Menu List */
.menu-list {
  list-style: none;
  padding: 80px 0 40px;
  margin: 0;
}

.menu-list li {
  margin: 0;
}

.menu-list a {
  display: block;
  padding: 18px 30px;
  font-size: 1.1em;
  font-weight: 500;
  color: #2c3e50;
  text-decoration: none;
  border-left: 4px solid transparent;
  transition: all 0.2s;
}

.menu-list a:hover,
.menu-list a:focus {
  background: #f093fb;
  color: white;
  border-left-color: #f5576c;
}

/* Close Button */
.close-menu {
  position: absolute;
  top: 20px;
  right: 20px;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 10px;
  color: #2c3e50;
  transition: color 0.2s;
}

.close-menu:hover {
  color: #f5576c;
}

/* Menu Footer */
.menu-footer {
  padding: 20px 30px;
  border-top: 1px solid #e9ecef;
  display: flex;
  gap: 20px;
}

.menu-footer a {
  color: #6c757d;
  font-size: 0.9em;
  text-decoration: none;
}

/* Prevent body scroll when menu open */
body.menu-open {
  overflow: hidden;
}

JavaScript Functionality:

// Get elements
const hamburger = document.querySelector('.hamburger');
const mobileMenu = document.querySelector('.mobile-menu');
const menuBackdrop = document.querySelector('.menu-backdrop');
const closeMenu = document.querySelector('.close-menu');
const body = document.body;

// Open menu
function openMenu() {
  hamburger.classList.add('active');
  mobileMenu.classList.add('active');
  menuBackdrop.classList.add('active');
  body.classList.add('menu-open');
  
  // Accessibility
  hamburger.setAttribute('aria-expanded', 'true');
  mobileMenu.setAttribute('aria-hidden', 'false');
  
  // Focus first link
  const firstLink = mobileMenu.querySelector('a');
  setTimeout(() => firstLink.focus(), 300);
}

// Close menu
function closeMenuFn() {
  hamburger.classList.remove('active');
  mobileMenu.classList.remove('active');
  menuBackdrop.classList.remove('active');
  body.classList.remove('menu-open');
  
  // Accessibility
  hamburger.setAttribute('aria-expanded', 'false');
  mobileMenu.setAttribute('aria-hidden', 'true');
  
  // Return focus
  hamburger.focus();
}

// Event listeners
hamburger.addEventListener('click', openMenu);
closeMenu.addEventListener('click', closeMenuFn);
menuBackdrop.addEventListener('click', closeMenuFn);

// Close on Escape key
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape' && mobileMenu.classList.contains('active')) {
    closeMenuFn();
  }
});

// Close menu on link click
const menuLinks = mobileMenu.querySelectorAll('a');
menuLinks.forEach(link => {
  link.addEventListener('click', () => {
    // Delay for navigation
    setTimeout(closeMenuFn, 200);
  });
});

♿ Accessibility Best Practices

ARIA Attributes

  • aria-label="Menu" на button
  • aria-expanded="false|true" (toggle state)
  • aria-controls="mobile-menu" (connects button до menu)
  • aria-hidden="true|false" на nav

Keyboard Navigation

  • Tab: Navigate через links
  • Escape: Close menu
  • Space/Enter: Activate hamburger
  • Focus trap: Keep focus у menu коли open

Screen Reader Support

  • Descriptive button label
  • Announce state changes
  • Skip links available
  • Semantic HTML (<nav>, <button>)

Touch Targets

  • Minimum: 44x44px (WCAG 2.1)
  • Hamburger: 48x48px recommended
  • Menu items: ≥ 48px height
  • Spacing: 8px minimum між items

⚡ Performance & UX Tips

Animation Performance:

/* Use GPU-accelerated properties */
.mobile-menu {
  /* ✅ Good: GPU accelerated */
  transform: translateX(100%);
  will-change: transform;
  
  /* ❌ Avoid: triggers layout/paint */
  /* left: 100%; */
}

/* Use cubic-bezier для smooth easing */
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);

Prevent Body Scroll:

// When menu opens
body.classList.add('menu-open');

// CSS
body.menu-open {
  overflow: hidden;
  position: fixed; /* iOS fix */
  width: 100%;
}

Debounce Resize Events:

// Close menu if resized to desktop
let resizeTimer;
window.addEventListener('resize', () => {
  clearTimeout(resizeTimer);
  resizeTimer = setTimeout(() => {
    if (window.innerWidth > 768 && mobileMenu.classList.contains('active')) {
      closeMenuFn();
    }
  }, 250);
});

✅ Mobile Menu Checklist

Implementation Checklist:

  • ☐ Hamburger icon має proper ARIA labels
  • ☐ Smooth animation (≤ 300ms)
  • ☐ Backdrop overlay з opacity transition
  • ☐ Body scroll prevented коли menu open
  • ☐ Close button visible та accessible
  • ☐ Click backdrop closes menu
  • ☐ Escape key closes menu
  • ☐ Focus management (trap, return)
  • ☐ Touch targets ≥ 44x44px
  • ☐ Screen reader tested
  • ☐ Keyboard navigation works
  • ☐ Responsive auto-close на desktop resize
  • ☐ Performance optimized (GPU acceleration)
  • ☐ Active state indicator
  • ☐ Works на iOS/Android