إطار Tailwind CSS

بناء مكونات التنقل والرأس

25 دقيقة الدرس 28 من 35

بناء مكونات التنقل والرأس

تعلم كيفية بناء مكونات تنقل احترافية ومتجاوبة من الصفر باستخدام Tailwind CSS. أتقن القوائم المحمولة، القوائم المنسدلة، الرؤوس الثابتة، وأفضل ممارسات إمكانية الوصول.

هيكل شريط التنقل الأساسي

ابدأ بهيكل HTML دلالي لتنقلك:

HTML بسيط لشريط التنقل

<nav class="bg-white shadow-lg">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex justify-between h-16">
      <!-- الشعار -->
      <div class="flex items-center">
        <a href="/" class="flex-shrink-0 flex items-center">
          <img class="h-8 w-auto" src="/logo.svg" alt="Logo">
        </a>
      </div>

      <!-- تنقل سطح المكتب -->
      <div class="hidden md:flex md:items-center md:space-x-8">
        <a href="/about" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
          About
        </a>
        <a href="/services" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
          Services
        </a>
        <a href="/contact" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
          Contact
        </a>
      </div>

      <!-- زر قائمة المحمول -->
      <div class="md:hidden flex items-center">
        <button type="button" class="text-gray-700 hover:text-blue-600">
          <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
          </svg>
        </button>
      </div>
    </div>
  </div>
</nav>
HTML دلالي: استخدم <nav> لمعالم التنقل، <a> للروابط، و <button> للعناصر التفاعلية. هذا يحسن إمكانية الوصول و SEO.

قائمة المحمول المتجاوبة

أنشئ قائمة محمول تبديل الرؤية بـ JavaScript:

شريط تنقل كامل مع قائمة محمول

<nav class="bg-white shadow-lg">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex justify-between h-16">
      <div class="flex items-center">
        <a href="/" class="flex-shrink-0">
          <img class="h-8 w-auto" src="/logo.svg" alt="Logo">
        </a>
      </div>

      <!-- قائمة سطح المكتب -->
      <div class="hidden md:flex md:items-center md:space-x-4">
        <a href="/" class="text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
          Home
        </a>
        <a href="/about" class="text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
          About
        </a>
        <a href="/services" class="text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
          Services
        </a>
        <a href="/contact" class="bg-blue-600 text-white hover:bg-blue-700 px-4 py-2 rounded-md text-sm font-medium transition-colors">
          Contact Us
        </a>
      </div>

      <!-- زر قائمة المحمول -->
      <div class="md:hidden flex items-center">
        <button
          id="mobile-menu-button"
          type="button"
          class="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-blue-600 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500"
          aria-expanded="false"
          aria-controls="mobile-menu"
        >
          <span class="sr-only">Open main menu</span>
          <!-- أيقونة همبرغر -->
          <svg id="menu-open-icon" class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
          </svg>
          <!-- أيقونة إغلاق -->
          <svg id="menu-close-icon" class="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
          </svg>
        </button>
      </div>
    </div>
  </div>

  <!-- لوحة قائمة المحمول -->
  <div id="mobile-menu" class="hidden md:hidden">
    <div class="px-2 pt-2 pb-3 space-y-1">
      <a href="/" class="block text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-base font-medium">
        Home
      </a>
      <a href="/about" class="block text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-base font-medium">
        About
      </a>
      <a href="/services" class="block text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-base font-medium">
        Services
      </a>
      <a href="/contact" class="block bg-blue-600 text-white hover:bg-blue-700 px-3 py-2 rounded-md text-base font-medium">
        Contact Us
      </a>
    </div>
  </div>
</nav>

<script>
  const menuButton = document.getElementById('mobile-menu-button');
  const mobileMenu = document.getElementById('mobile-menu');
  const openIcon = document.getElementById('menu-open-icon');
  const closeIcon = document.getElementById('menu-close-icon');

  menuButton.addEventListener('click', () => {
    const isOpen = mobileMenu.classList.contains('hidden');

    mobileMenu.classList.toggle('hidden');
    openIcon.classList.toggle('hidden');
    closeIcon.classList.toggle('hidden');
    menuButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
  });
</script>
انتقالات سلسة: أضف فئات الانتقال مثل transition-all duration-300 ease-in-out إلى قائمة المحمول لفتح/إغلاق رسوم متحركة سلسة. يمكنك أيضاً استخدام انتقالات من max-h-0 إلى max-h-screen بدلاً من hidden.

رأس التنقل الثابت

أنشئ شريط تنقل يلتصق بالأعلى عند التمرير:

شريط تنقل ثابت مع تأثيرات التمرير

<nav id="navbar" class="sticky top-0 z-50 bg-white shadow-md transition-all duration-300">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex justify-between h-16">
      <div class="flex items-center">
        <a href="/" class="font-bold text-xl text-blue-600">
          Brand
        </a>
      </div>

      <div class="flex items-center space-x-4">
        <a href="#home" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">Home</a>
        <a href="#about" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">About</a>
        <a href="#services" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">Services</a>
        <a href="#contact" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">Contact</a>
      </div>
    </div>
  </div>
</nav>

<script>
  const navbar = document.getElementById('navbar');
  let lastScroll = 0;

  window.addEventListener('scroll', () => {
    const currentScroll = window.pageYOffset;

    if (currentScroll > 100) {
      // أضف ظلاً وقلل الارتفاع عند التمرير
      navbar.classList.add('shadow-lg');
      navbar.querySelector('div').classList.remove('h-16');
      navbar.querySelector('div').classList.add('h-14');
    } else {
      // أعد إلى الحالة الأصلية
      navbar.classList.remove('shadow-lg');
      navbar.querySelector('div').classList.remove('h-14');
      navbar.querySelector('div').classList.add('h-16');
    }

    lastScroll = currentScroll;
  });
</script>

القوائم المنسدلة

ابنِ قوائم منسدلة يمكن الوصول إليها لعناصر التنقل مع عناصر فرعية:

شريط تنقل مع قائمة منسدلة

<nav class="bg-white shadow-lg">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex justify-between h-16">
      <div class="flex items-center space-x-8">
        <a href="/" class="font-bold text-xl text-blue-600">Brand</a>

        <a href="/about" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
          About
        </a>

        <!-- منسدلة -->
        <div class="relative group">
          <button class="flex items-center text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium group">
            Services
            <svg class="ml-1 h-4 w-4 transition-transform group-hover:rotate-180" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
            </svg>
          </button>

          <!-- قائمة منسدلة -->
          <div class="absolute left-0 mt-2 w-48 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 transform group-hover:translate-y-0 -translate-y-2">
            <div class="bg-white rounded-lg shadow-xl ring-1 ring-black ring-opacity-5 py-1">
              <a href="/web-design" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">
                Web Design
              </a>
              <a href="/web-development" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">
                Web Development
              </a>
              <a href="/seo" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">
                SEO Services
              </a>
              <a href="/hosting" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">
                Hosting
              </a>
            </div>
          </div>
        </div>

        <a href="/contact" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
          Contact
        </a>
      </div>
    </div>
  </div>
</nav>
التمرير مقابل النقر: نمط group-hover يعمل بشكل جيد على سطح المكتب ولكن ليس على المحمول. للإنتاج، استخدم JavaScript لتبديل القوائم المنسدلة عند النقر لأجهزة المحمول، واحتفظ بسلوك التمرير لسطح المكتب.

تنسيق الرابط النشط

سلط الضوء على الصفحة الحالية في التنقل:

تنفيذ الحالة النشطة

<!-- HTML مع الفئات النشطة -->
<nav class="bg-white shadow-lg">
  <div class="max-w-7xl mx-auto px-4">
    <div class="flex space-x-4">
      <a
        href="/"
        class="px-3 py-2 text-sm font-medium rounded-md
               text-blue-600 bg-blue-50 border-b-2 border-blue-600"
        aria-current="page"
      >
        Home
      </a>
      <a
        href="/about"
        class="px-3 py-2 text-sm font-medium rounded-md
               text-gray-700 hover:text-blue-600 hover:bg-blue-50"
      >
        About
      </a>
      <a
        href="/services"
        class="px-3 py-2 text-sm font-medium rounded-md
               text-gray-700 hover:text-blue-600 hover:bg-blue-50"
      >
        Services
      </a>
    </div>
  </div>
</nav>

<!-- JavaScript لتعيين الرابط النشط -->
<script>
  // احصل على مسار الصفحة الحالية
  const currentPath = window.location.pathname;

  // ابحث عن جميع روابط التنقل
  const navLinks = document.querySelectorAll('nav a');

  navLinks.forEach(link => {
    // أزل الفئات النشطة من جميع الروابط
    link.classList.remove('text-blue-600', 'bg-blue-50', 'border-b-2', 'border-blue-600');
    link.removeAttribute('aria-current');

    // أضف الفئات النشطة إلى رابط الصفحة الحالية
    if (link.getAttribute('href') === currentPath) {
      link.classList.add('text-blue-600', 'bg-blue-50', 'border-b-2', 'border-blue-600');
      link.setAttribute('aria-current', 'page');
    }
  });
</script>

تنقل التنقل التفصيلي

أنشئ تنقلاً تفصيلياً لإظهار التسلسل الهرمي للصفحة:

مكون التنقل التفصيلي

<nav class="flex py-3 px-5 bg-gray-50 rounded-lg" aria-label="Breadcrumb">
  <ol class="inline-flex items-center space-x-1 md:space-x-3">
    <li class="inline-flex items-center">
      <a href="/" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600">
        <svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20">
          <path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path>
        </svg>
        Home
      </a>
    </li>
    <li>
      <div class="flex items-center">
        <svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
        </svg>
        <a href="/products" class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2">
          Products
        </a>
      </div>
    </li>
    <li aria-current="page">
      <div class="flex items-center">
        <svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
          <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
        </svg>
        <span class="ml-1 text-sm font-medium text-gray-500 md:ml-2">
          Laptops
        </span>
      </div>
    </li>
  </ol>
</nav>

نمط القائمة الضخمة

ابنِ قائمة منسدلة كبيرة مع أعمدة متعددة:

تنقل القائمة الضخمة

<nav class="bg-white shadow-lg">
  <div class="max-w-7xl mx-auto px-4">
    <div class="flex justify-between h-16">
      <div class="flex items-center space-x-8">
        <a href="/" class="font-bold text-xl">Brand</a>

        <!-- محفز القائمة الضخمة -->
        <div class="relative group">
          <button class="flex items-center px-3 py-2 text-sm font-medium text-gray-700 hover:text-blue-600">
            Products
            <svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
            </svg>
          </button>

          <!-- لوحة القائمة الضخمة -->
          <div class="absolute left-0 w-screen max-w-7xl opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
            <div class="mt-2 bg-white rounded-lg shadow-2xl ring-1 ring-black ring-opacity-5">
              <div class="grid grid-cols-4 gap-8 p-8">
                <!-- عمود 1 -->
                <div>
                  <h3 class="text-sm font-semibold text-gray-900 uppercase tracking-wider mb-4">
                    Electronics
                  </h3>
                  <ul class="space-y-3">
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Smartphones</a>
                    </li>
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Laptops</a>
                    </li>
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Tablets</a>
                    </li>
                  </ul>
                </div>

                <!-- عمود 2 -->
                <div>
                  <h3 class="text-sm font-semibold text-gray-900 uppercase tracking-wider mb-4">
                    Fashion
                  </h3>
                  <ul class="space-y-3">
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Men's Clothing</a>
                    </li>
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Women's Clothing</a>
                    </li>
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Accessories</a>
                    </li>
                  </ul>
                </div>

                <!-- عمود 3 -->
                <div>
                  <h3 class="text-sm font-semibold text-gray-900 uppercase tracking-wider mb-4">
                    Home & Living
                  </h3>
                  <ul class="space-y-3">
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Furniture</a>
                    </li>
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Decor</a>
                    </li>
                    <li>
                      <a href="#" class="text-sm text-gray-700 hover:text-blue-600">Kitchen</a>
                    </li>
                  </ul>
                </div>

                <!-- عمود 4 مع صورة -->
                <div class="bg-blue-50 rounded-lg p-6">
                  <h3 class="text-sm font-semibold text-gray-900 mb-2">
                    New Arrivals
                  </h3>
                  <p class="text-sm text-gray-600 mb-4">
                    Check out our latest products
                  </p>
                  <a href="#" class="inline-flex items-center text-sm font-medium text-blue-600 hover:text-blue-700">
                    Shop Now
                    <svg class="ml-1 w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
                    </svg>
                  </a>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</nav>
وضع القائمة الضخمة: استخدم left-0 أو left-1/2 -translate-x-1/2 لتوسيط القوائم الضخمة. كن حذراً مع w-screen على القوائم الضخمة - يمكن أن يسبب التمرير الأفقي. فكر في استخدام قيود مثل max-w-7xl.

أفضل ممارسات إمكانية الوصول (ARIA)

اجعل تنقلك قابلاً للوصول لقارئات الشاشة ومستخدمي لوحة المفاتيح:

مثال تنقل قابل للوصول

<nav aria-label="Main navigation" class="bg-white shadow-lg">
  <div class="max-w-7xl mx-auto px-4">
    <div class="flex justify-between h-16">
      <!-- الشعار -->
      <div class="flex items-center">
        <a href="/" aria-label="Homepage">
          <img src="/logo.svg" alt="Company Logo" class="h-8">
        </a>
      </div>

      <!-- روابط التنقل -->
      <ul class="flex items-center space-x-4" role="menubar">
        <li role="none">
          <a
            href="/"
            role="menuitem"
            class="text-gray-700 hover:text-blue-600 px-3 py-2"
            aria-current="page"
          >
            Home
          </a>
        </li>
        <li role="none">
          <a
            href="/about"
            role="menuitem"
            class="text-gray-700 hover:text-blue-600 px-3 py-2"
          >
            About
          </a>
        </li>

        <!-- منسدلة مع ARIA -->
        <li role="none" class="relative">
          <button
            id="services-button"
            role="menuitem"
            aria-haspopup="true"
            aria-expanded="false"
            aria-controls="services-menu"
            class="flex items-center text-gray-700 hover:text-blue-600 px-3 py-2"
          >
            Services
            <svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
            </svg>
          </button>

          <ul
            id="services-menu"
            role="menu"
            aria-labelledby="services-button"
            class="absolute left-0 mt-2 w-48 bg-white rounded-lg shadow-xl hidden"
          >
            <li role="none">
              <a href="/web-design" role="menuitem" class="block px-4 py-2 text-sm hover:bg-blue-50">
                Web Design
              </a>
            </li>
            <li role="none">
              <a href="/web-dev" role="menuitem" class="block px-4 py-2 text-sm hover:bg-blue-50">
                Web Development
              </a>
            </li>
          </ul>
        </li>
      </ul>

      <!-- زر قائمة المحمول مع ARIA -->
      <button
        type="button"
        aria-label="Toggle navigation menu"
        aria-expanded="false"
        aria-controls="mobile-menu"
        class="md:hidden"
      >
        <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
        </svg>
      </button>
    </div>
  </div>
</nav>
التنقل بلوحة المفاتيح: تأكد من أن القوائم المنسدلة يمكن فتحها بمفاتيح Enter/Space والتنقل فيها بمفاتيح الأسهم. أضف tabindex="0" للعناصر القابلة للتركيز وقم بتنفيذ مستمعي أحداث لوحة المفاتيح لإمكانية الوصول المناسبة.

تمرين 1: شريط تنقل متجاوب

ابنِ مكون تنقل متجاوب كامل:

  • شعار على اليسار
  • 4-5 روابط تنقل (أفقية لسطح المكتب، عمودية للمحمول)
  • قائمة همبرغر للمحمول (مع انتقال سلس)
  • زر CTA (مثل "ابدأ")
  • تسليط الضوء على الصفحة النشطة

تمرين 2: رأس ثابت مع تأثيرات

أنشئ رأساً ثابتاً يتغير عند التمرير:

  • يبدأ بارتفاع أكبر (h-20)
  • ينكمش إلى ارتفاع أصغر (h-14) بعد التمرير 100 بكسل
  • تتغير الخلفية من شفافة إلى بيضاء صلبة
  • يزداد الظل عند التمرير
  • انتقالات سلسة لجميع التغييرات

تمرين 3: قائمة ضخمة قابلة للوصول

ابنِ تنقل قائمة ضخمة قابلة للوصول:

  • 3-4 عناصر تنقل رئيسية
  • عنصر واحد يفتح قائمة ضخمة بـ 3 أعمدة
  • قم بتضمين أيقونات أو صور في القائمة الضخمة
  • سمات ARIA مناسبة لقارئات الشاشة
  • دعم التنقل بلوحة المفاتيح (Tab، Enter، Escape)
  • يعمل على كل من التمرير (سطح المكتب) والنقر (المحمول)