Mega Menu Implementation for Website

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1212
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    815

Mega Menu Implementation on Website

Mega menu is a navigation component that reveals a multi-column panel with grouped links, images, descriptions and additional control elements. Applied on sites with deep section structure: e-commerce, portals, corporate sites with several product lines. Standard dropdown list becomes bottleneck when there are 20+ sections and user needs context along with navigation.

When Standard Menu Stops Working

Regular dropdown list (<ul> with position: absolute) has rigid limitations:

  • single column — impossible to group by categories
  • no space for helper content (images, descriptions, promo blocks)
  • on touch devices hover logic breaks
  • keyboard management either missing or hastily implemented

Mega menu solves these problems through different reveal model and markup.

Component Architecture

Typical mega menu structure consists of three layers:

Top-level triggers — horizontal navigation bar. Each item is either a link or button revealing panel. Semantically: <button aria-expanded="false" aria-controls="menu-catalog">.

Panel<div role="dialog"> or just <div> with aria-labelledby, absolutely or fixed positioned, spanning container full width (or viewport). Inside — CSS Grid or Flexbox with multiple columns.

Content inside panel — link groups with titles, featured blocks, images, CTA buttons. Structured through <nav> + <ul> inside named sections.

<nav aria-label="Main navigation">
  <ul class="mega-nav">
    <li>
      <button
        aria-expanded="false"
        aria-controls="panel-catalog"
        class="mega-nav__trigger"
      >
        Catalog
      </button>
      <div id="panel-catalog" class="mega-panel" hidden>
        <div class="mega-panel__grid">
          <section aria-labelledby="group-electronics">
            <h3 id="group-electronics">Electronics</h3>
            <ul>
              <li><a href="/catalog/phones">Phones</a></li>
              <li><a href="/catalog/laptops">Laptops</a></li>
            </ul>
          </section>
          <!-- other groups -->
        </div>
      </div>
    </li>
  </ul>
</nav>

React Implementation

In React projects mega menu is usually managed through context or local state with useReducer. Open/close animations — via Framer Motion or CSS transformations.

const MegaMenu = () => {
  const [activePanel, setActivePanel] = useState<string | null>(null);
  const containerRef = useRef<HTMLElement>(null);

  // Close on click outside
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setActivePanel(null);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  // Close on Escape
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setActivePanel(null);
    };
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, []);

  return (
    <nav ref={containerRef} aria-label="Main navigation">
      {navItems.map((item) => (
        <MegaNavItem
          key={item.id}
          item={item}
          isOpen={activePanel === item.id}
          onToggle={() => setActivePanel(activePanel === item.id ? null : item.id)}
        />
      ))}
    </nav>
  );
};

If menu is used in Next.js with SSR, panel hidden attribute should be handled correctly on server to avoid layout shift on hydration.

Accessibility (WCAG 2.1 AA)

This is most often ignored part. Requirements are specific:

Pattern Implementation
Opening on Enter/Space on trigger onKeyDown with `key === 'Enter'
Arrow navigation inside panel roving tabindex or aria-activedescendant
Closing on Escape global handler or via FocusTrap
Focus on close return to trigger via triggerRef.current?.focus()
Hiding from screen reader hidden or aria-hidden="true" on closed panel

Library @radix-ui/react-navigation-menu implements most of these requirements out of box and is preferred base for custom mega menu in React stack. It uses NavigationMenu.Root + NavigationMenu.List + NavigationMenu.Item + NavigationMenu.Trigger + NavigationMenu.Content pattern.

Mobile Version

Mega menu on mobile devices transforms to accordion or drawer panel. This is different component, not just adapted desktop. CSS breakpoint logic:

@media (max-width: 1024px) {
  .mega-panel {
    position: static;
    display: grid;
    grid-template-rows: 0fr;
    overflow: hidden;
    transition: grid-template-rows 0.3s ease;
  }

  .mega-panel[data-open="true"] {
    grid-template-rows: 1fr;
  }
}

Trick with grid-template-rows: 0fr → 1fr allows height animation without fixed value — established pattern for accordions without JavaScript height measurement.

Panel Positioning

Two main approaches:

Full-width — panel stretches navbar full page width, anchored to bottom of navigation bar. Used in most e-commerce sites. Implemented via position: fixed with top: <navbar-height> or via position: absolute on wrapper with overflow: visible.

Flyout — panel positioned relative to specific trigger. Fits menus with small group count. Requires position calculation via getBoundingClientRect() for correct edge behavior (flip logic, like Floating UI / Popper.js).

Performance

Mega menu panels contain many DOM nodes. If content loads from API (e.g., dynamic catalog categories), important to:

  • render panels lazily — only after first open (mountedPanels: Set<string>)
  • use content-visibility: auto for hidden sections
  • limit number of simultaneously mounted panels
const [mounted, setMounted] = useState(false);

const handleOpen = () => {
  if (!mounted) setMounted(true);
  setIsOpen(true);
};

return (
  <div>
    <button onClick={handleOpen}>Catalog</button>
    {mounted && (
      <div hidden={!isOpen} className="mega-panel">
        <CatalogPanelContent />
      </div>
    )}
  </div>
);

Typical Implementation Timeline

  • Static mega menu (fixed links, no API) with mobile accordion — 3–5 days
  • Dynamic menu with category loading from CMS/API + full accessibility + animations — 7–10 days
  • Integration into existing design system component with unit/a11y tests — add 2–3 days