组件 导航 电商 Material Design 导航

电商 Material Design 导航

一个复杂的响应式单色电子商务导航组件,其灵感来自 Material Design,具有搜索、购物车、用户资料和类别链接,并支持深色模式。

预览

HTML 代码

<header class="bg-white dark:bg-gray-900 shadow-md font-sans w-full">
  <div class="container mx-auto px-4 py-3 sm:py-4 flex flex-wrap items-center justify-between">
    <!-- Logo & Brand Name -->
    <a href="#" class="flex items-center text-gray-900 dark:text-white text-2xl font-bold tracking-tight">
      <svg class="h-8 w-8 mr-2 text-indigo-600 dark:text-indigo-400" fill="currentColor" viewBox="0 0 24 24">
        <path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-3.5 16.5c-.828 0-1.5-.672-1.5-1.5s.672-1.5 1.5-1.5 1.5.672 1.5 1.5-.672 1.5-1.5 1.5zm7 0c-.828 0-1.5-.672-1.5-1.5s.672-1.5 1.5-1.5 1.5.672 1.5 1.5-.672 1.5-1.5 1.5zm-3.5-5c-.828 0-1.5-.672-1.5-1.5s.672-1.5 1.5-1.5 1.5.672 1.5 1.5-.672 1.5-1.5 1.5z"/>
      </svg>
      ShopHere
    </a>

    <!-- Search Bar (Desktop/Tablet) -->
    <div class="hidden md:flex flex-grow max-w-lg mx-4">
      <div class="relative w-full">
        <input type="text" placeholder="Search products..." class="w-full pl-10 pr-4 py-2 rounded-full border border-gray-300 dark:border-gray-700 bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 dark:focus:border-indigo-400 shadow-sm">
        <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
          <svg class="h-5 w-5 text-gray-500 dark:text-gray-400" fill="currentColor" viewBox="0 0 20 20">
            <path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"/>
          </svg>
        </div>
      </div>
    </div>

    <!-- Right-aligned Icons (Profile, Cart, etc.) -->
    <div class="flex items-center space-x-4 sm:space-x-6">
      <!-- User Profile Dropdown -->
      <div class="relative group">
        <button class="flex items-center p-2 rounded-full bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400">
          <img class="h-8 w-8 rounded-full object-cover" src="https://randomuser.me/api/portraits/men/32.jpg" alt="User Avatar">
        </button>
        <div class="absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-1 z-10 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-300 transform scale-95 group-hover:scale-100 origin-top-right">
          <a href="#" class="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">My Profile</a>
          <a href="#" class="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Orders</a>
          <a href="#" class="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Wishlist</a>
          <hr class="my-1 border-gray-200 dark:border-gray-700">
          <a href="#" class="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Sign Out</a>
        </div>
      </div>

      <!-- Cart Icon -->
      <a href="#" class="relative p-2 rounded-full text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400">
        <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"/>
        </svg>
        <span class="absolute top-0 right-0 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-red-100 bg-red-600 rounded-full dark:bg-red-500 dark:text-white transform translate-x-1/2 -translate-y-1/2">3</span>
      </a>

      <!-- Mobile Menu Button -->
      <div class="md:hidden">
        <button id="mobile-menu-button" class="p-2 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400">
          <svg class="h-6 w-6" fill="currentColor" viewBox="0 0 20 20">
            <path id="mobile-menu-open-icon" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clip-rule="evenodd"/>
            <path id="mobile-menu-close-icon" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
          </svg>
        </button>
      </div>
    </div>

    <!-- Mobile Search Bar -->
    <div class="w-full mt-3 md:hidden">
      <div class="relative w-full">
        <input type="text" placeholder="Search products..." class="w-full pl-10 pr-4 py-2 rounded-full border border-gray-300 dark:border-gray-700 bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400 focus:border-indigo-500 dark:focus:border-indigo-400 shadow-sm">
        <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
          <svg class="h-5 w-5 text-gray-500 dark:text-gray-400" fill="currentColor" viewBox="0 0 20 20">
            <path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"/>
          </svg>
        </div>
      </div>
    </div>
  </div>

  <!-- Main Navigation Links -->
  <nav id="main-navigation" class="bg-gray-100 dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 h-0 hidden md:flex md:h-auto overflow-hidden transition-all duration-300 ease-linear-out md:overflow-visible" style="opacity: 0;">
    <div class="container mx-auto px-4 py-2">
      <ul class="flex flex-col md:flex-row md:justify-around lg:justify-center md:space-x-8 lg:space-x-12">
        <li>
          <a href="#" class="block py-2 px-3 text-gray-800 dark:text-gray-200 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors duration-200 md:px-0 md:py-0">
            Home
          </a>
        </li>
        <li class="relative group">
          <a href="#" class="block py-2 px-3 text-gray-800 dark:text-gray-200 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors duration-200 md:px-0 md:py-0 flex items-center">
            Categories
            <svg class="ml-1 h-4 w-4 transform group-hover:rotate-180 transition-transform duration-200" fill="currentColor" viewBox="0 0 20 20">
              <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/>
            </svg>
          </a>
          <div class="absolute left-0 mt-2 py-2 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg z-10 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-300 transform scale-95 group-hover:scale-100 origin-top-left">
            <a href="#" class="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Electronics</a>
            <a href="#" class="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Apparel</a>
            <a href="#" class="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Home Goods</a>
            <a href="#" class="block px-4 py-2 text-gray-800 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700">Books</a>
          </div>
        </li>
        <li>
          <a href="#" class="block py-2 px-3 text-gray-800 dark:text-gray-200 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors duration-200 md:px-0 md:py-0">
            Deals
          </a>
        </li>
        <li>
          <a href="#" class="block py-2 px-3 text-gray-800 dark:text-gray-200 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors duration-200 md:px-0 md:py-0">
            New Arrivals
          </a>
        </li>
        <li>
          <a href="#" class="block py-2 px-3 text-gray-800 dark:text-gray-200 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors duration-200 md:px-0 md:py-0">
            Contact
          </a>
        </li>
      </ul>
    </div>
  </nav>
</header>

<script>
  document.addEventListener('DOMContentLoaded', () => {
    const mobileMenuButton = document.getElementById('mobile-menu-button');
    const mainNavigation = document.getElementById('main-navigation');
    const openIcon = document.getElementById('mobile-menu-open-icon');
    const closeIcon = document.getElementById('mobile-menu-close-icon');

    mobileMenuButton.addEventListener('click', () => {
      const isHidden = mainNavigation.classList.contains('hidden');
      if (isHidden) {
        mainNavigation.classList.remove('hidden');
        mainNavigation.style.height = mainNavigation.scrollHeight + 'px'; // Set height for smooth transition
        mainNavigation.style.opacity = '1';
        openIcon.classList.add('hidden');
        closeIcon.classList.remove('hidden');
      } else {
        mainNavigation.style.height = '0'; // Collapse height
        mainNavigation.style.opacity = '0';
        // Wait for transition to complete before hiding fully
        mainNavigation.addEventListener('transitionend', () => {
          if (mainNavigation.style.height === '0px') {
            mainNavigation.classList.add('hidden');
          }
        }, { once: true });
        openIcon.classList.remove('hidden');
        closeIcon.classList.add('hidden');
      }
    });

    // Handle window resize to collapse/show menu for desktop
    window.addEventListener('resize', () => {
      if (window.innerWidth >= 768) { // md breakpoint
        mainNavigation.classList.remove('hidden');
        mainNavigation.style.height = 'auto'; // Reset height for desktop
        mainNavigation.style.opacity = '1';
        openIcon.classList.remove('hidden'); // Ensure menu button is in 3-line state on desktop
        closeIcon.classList.add('hidden');
      } else {
        if (!mainNavigation.classList.contains('hidden')) {
            // If menu is open on mobile, collapse it when resizing to smaller than md
            mainNavigation.style.height = '0';
            mainNavigation.style.opacity = '0';
            mainNavigation.addEventListener('transitionend', () => {
              if (mainNavigation.style.height === '0px') {
                mainNavigation.classList.add('hidden');
              }
            }, { once: true });
            openIcon.classList.remove('hidden');
            closeIcon.classList.add('hidden');
        }
      }
    });
  });
</script>

相关组件

3D导航组件

一种为电子商务设计的响应式3D导航组件,具有灰度色彩方案和深色模式支持。

打开

导航组件

一个为深色模式设计并使用 Tailwind CSS 的响应式导航组件。

打开

复古电商导航

响应式导航组件,具有复古/复古设计、大地色调和深色模式支持电子商务。

打开