نوارهای ناوبری اجزای ضروری هستند که در وب سایت ها و برنامه های وب بسیار مورد استفاده قرار می گیرند. به عنوان یک توسعه دهنده وب، باید بتوانید آنها را سفارشی کنید، چه برای یک پروژه مشتری یا یک سایت نمونه کار اولیه.
در این راهنما، شما یاد خواهید گرفت که چگونه از ابتدا با استفاده از HTML، CSS و جاوا اسکریپت، یک پایه ناوبری برای خود بسازید. همچنین یاد خواهید گرفت که چگونه آن را در دسترس قرار دهید.
در اینجا یک اسکرین شات از شکل ظاهری این نوار پیمایش آمده است:

این طراحی از نوار ناوبری حداقلی Tran Mau Tri Tam در Dribbble الهام گرفته شده است.
مرحله ۱ - علامت گذاری HTML را اضافه کنید
برای اختصار، از یک کتابخانه نماد به نام boxicons برای وارد کردن نمادهای خاص برای این نوار ناوبری استفاده خواهیم کرد. من به شدت توصیه می کنم به جای آن از SVG های درون خطی استفاده کنید.
برای استفاده از این کتابخانه، قطعه زیر را در سر فایل HTML خود وارد کنید:
<link href='https://unpkg.com/boxic[email protected]/css/boxicons.min.css' rel='stylesheet'>
نشانه گذاری به سه بخش اصلی تقسیم می شود:
یک عنصر div
با کلاس nav-start
یکی دیگر از عناصر div
با کلاس nav-end
یک عنصر button
با شناسه hamburger
همه این عناصر در یک تگ header
محصور خواهند شد. برای توضیح بهتر این موضوع، نشانه گذاری زیر را کپی کنید و من توضیح خواهم داد که بعد از آن چه اتفاقی می افتد.
<header id="nav-menu" aria-label="navigation bar"> <div class="container"> <div class="nav-start"> <a class="logo" href="/"> <img src="https://github.com/Evavic44/responsive-navbar-with-dropdown/blob/main/assets/images/logo.png?raw=true" width="35" height="35" alt="Inc Logo" /> </a> <nav class="menu"></nav> </div> <div class="nav-end"> <div class="right-container"> <form class="search" role="search"> <input type="search" name="search" placeholder="Search" /> <i class="bx bx-search" aria-hidden="true"></i> </form> <a href="#profile"> <img src="https://github.com/Evavic44/responsive-navbar-with-dropdown/blob/main/assets/images/user.jpg?raw=true" width="30" height="30" alt="user image" /> </a> <button class="btn btn-primary">Create</button> </div> <button id="hamburger" aria-label="hamburger" aria-haspopup="true" aria-expanded="false"> <i class="bx bx-menu" aria-hidden="true"></i> </button> </div> </div> </header>
برای nav-start، عناصر زیر را داریم:
یک عنصر <img>
برای لوگو که با یک برچسب لنگر <a>
پیچیده شده است.
یک عنصر <nav>
با یک کلاس از menu
که شامل تمام پیوندهای ناوبری است. این پیوندها را بعداً با استفاده از ترکیبی از تگهای <ul>
، li>
و <a>
تعریف خواهیم کرد.
Nav-end دارای عناصر زیر است:
یک عنصر <form>
با نقش جستجو که حاوی ورودی جستجو و نماد جستجو است.
یک عنصر دکمه با کلاس btn
. ما از این کلاس برای استایل دادن به دکمه استفاده می کنیم.
برای دکمه همبرگر:
دکمه ای با شناسه و aria-label
همبرگر، aria-haspopup
روی "true" و aria-expanded
مجموعه روی "false". این برچسبها به ما امکان میدهند این دکمه را برای صفحهخوانها در دسترستر کنیم.
در اینجا خروجی حاصل آمده است:

منوی ناوبری <nav>
جایی است که پیوندهای ناوبری در آن قرار خواهند گرفت. عنصر nav
را که قبلاً اضافه کردید با این نشانه گذاری زیر جایگزین کنید:
<nav class="menu"> <ul class="menu-bar"> <li> <button class="nav-link dropdown-btn" data-dropdown="dropdown1" aria-haspopup="true" aria-expanded="false" aria-label="browse"> Browse <i class="bx bx-chevron-down" aria-hidden="true"></i> </button> <div id="dropdown1" class="dropdown"></div> </li> <li> <button class="nav-link dropdown-btn" data-dropdown="dropdown2" aria-haspopup="true" aria-expanded="false" aria-label="discover"> Discover <i class="bx bx-chevron-down" aria-hidden="true"></i> </button> <div id="dropdown2" class="dropdown"></div> </li> <li><a class="nav-link" href="/">Jobs</a></li> <li><a class="nav-link" href="/">Livestream</a></li> <li><a class="nav-link" href="/">About</a></li> </ul> </nav>
در اینجا شما یک تگ nav
دارید که حاوی فهرست نامرتب از پنج عنصر li
است که هر آیتم منوی پیمایش را نشان میدهد: مرور، کشف، مشاغل، پخش زنده و درباره .
دو عنصر اول، مرور و کشف ، عناصر button
هستند و برای تغییر منوی کشویی جداگانه استفاده میشوند. عناصر باقیمانده Jobs، پخش زنده و در مورد ، فقط پیوندهای معمولی هستند.
با کدی که تا اینجای کار دارید، نتیجه شما باید به این صورت باشد:

عنصر کشویی
در مرحله بعد، اجازه دهید عنصر کشویی را برای هر دکمه ناوبری تعریف کنیم. در اینجا نشانه گذاری برای اولین کشویی است. اولین عنصر li
را در نشانه گذاری خود با این جایگزین کنید:
<!-- markup truncated for brevity--> <li> <button class="nav-link dropdown-btn" data-dropdown="dropdown1" aria-haspopup="true" aria-expanded="false" aria-label="browse" > Browse <i class="bx bx-chevron-down" aria-hidden="true"></i> </button> <div id="dropdown1" class="dropdown"> <ul role="menu"> <li role="menuitem"> <a class="dropdown-link" href="#best-of-the-day"> <img src="./assets/icons/botd.svg" class="icon" /> <div> <span class="dropdown-link-title" >Best of the day</span > <p>Shorts featured today by curators</p> </div> </a> </li> <li role="menuitem"> <a class="dropdown-link" href="#featured-streams"> <img src="./assets/icons/fs.svg" class="icon" /> <div> <span class="dropdown-link-title" >Featured Streams</span > <p>Leading creatives livestreams</p> </div> </a> </li> <li role="menuitem"> <a class="dropdown-link" href="#subscriptions"> <img src="./assets/icons/sp.svg" class="icon" /> <div> <span class="dropdown-link-title">Subscriptions</span> <p>Gain exclusive access</p> </div> </a> </li> <li role="menuitem"> <a class="dropdown-link" href="#creative-feed"> <img src="./assets/icons/cf.svg" class="icon" /> <div> <span class="dropdown-link-title">Creative Feed</span> <p>See trending creations</p> </div> </a> </li> </ul> <ul role="menu"> <li class="dropdown-title"> <span class="dropdown-link-title">Browse by apps</span> </li> <li role="menuitem"> <a class="dropdown-link" href="#adobe-xd"> <img src="./assets/icons/xd.svg" /> Adobe XD </a> </li> <li role="menuitem"> <a class="dropdown-link" href="#after-effect"> <img src="./assets/icons/ae.svg" /> After Effect </a> </li> <li role="menuitem"> <a class="dropdown-link" href="#sketch"> <img src="./assets/icons/sketch.svg" /> Sketch </a> </li> <li role="menuitem"> <a class="dropdown-link" href="#indesign"> <img src="./assets/icons/indesign.svg" /> Indesign </a> </li> <li role="menuitem"> <a class="dropdown-link" href="#figma"> <img src="./assets/icons/figma.svg" /> Figma </a> </li> </ul> </div> </li>
می توانید نمادهای SVG را از اینجا دریافت کنید.
برای تجزیه این نشانه گذاری، موارد زیر را اضافه کردیم:
یک عنصر div
با شناسه dropdown1
و کلاس dropdown
.
دو عنصر ul
هر کدام یک نقش "menu"
را به خود اختصاص دادند.
یک عنصر span
با یک کلاس از dropdown-link-title
برای سرصفحه هر مجموعه menu
.
مجموعه ای از پیوندها که با استفاده از li
و a
تعریف شده اند. تگهای li
نقش "menuitem"
را دارند و پیوندها هر یک دارای یک کلاس dropdown-link
هستند.
در داخل هر تگ لنگر، یک آیکون از طریق تگ img
اضافه می شود.
توجه: از آنجایی که آیکون هایی که از طریق تگ img
اضافه می شوند کاملاً بیانی هستند، پیشنهاد می کنم آنها را مستقیماً به عنوان عناصر SVG اضافه کنید. من این کار را فقط برای خوانایی بیشتر کد انجام می دهم.
در اینجا نشانه گذاری برای دومین عنصر کشویی dropdown2
است:
<!-- markup truncated for brevity--> <li> <button class="nav-link dropdown-btn" data-dropdown="dropdown2" aria-haspopup="true" aria-expanded="false" aria-label="discover" > Discover <i class="bx bx-chevron-down" aria-hidden="true"></i> </button> <div id="dropdown2" class="dropdown"> <ul role="menu"> <li> <span class="dropdown-link-title">Browse Categories</span> </li> <li role="menuitem"> <a class="dropdown-link" href="#branding">Branding</a> </li> <li role="menuitem"> <a class="dropdown-link" href="#illustrations">Illustration</a> </li> </ul> <ul role="menu"> <li> <span class="dropdown-link-title">Download App</span> </li> <li role="menuitem"> <a class="dropdown-link" href="#mac-windows">MacOS & Windows</a> </li> <li role="menuitem"> <a class="dropdown-link" href="#linux">Linux</a> </li> </ul> </div> </li>
نتیجه نهایی باید به این صورت باشد:

نشانه گذاری کامل در پایان این آموزش ارائه خواهد شد.
مرحله ۲ - نوار پیمایش را سبک کنید
مثل همیشه، ما با بازنشانی حاشیه پیشفرض و padding هر عنصر در صفحه، اضافه کردن متغیرهای سراسری و برخی استایل اولیه به چند عنصر شروع میکنیم.
/* style.css */ @import url("https://fonts.googleapis.com/css2?family=Inter:[email protected];300;400;500;600;700&display=swap"); * { margin: 0; padding: 0; box-sizing: border-box; font-family: "Inter", sans-serif; } :root { --dark-grey: #333333; --medium-grey: #636363; --light-grey: #eeeeee; --ash: #f4f4f4; --primary-color: #2b72fb; --white: white; --border: 1px solid var(--light-grey); --shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px, rgba(0, 0, 0, 0.08) 0px 0px 0px 1px; } body { font-family: inherit; background-color: var(--white); color: var(--dark-grey); letter-spacing: -0.4px; } ul { list-style: none; } a { text-decoration: none; color: inherit; } button { border: none; background-color: transparent; cursor: pointer; color: inherit; }
بعد، چند سبک قابل استفاده مجدد اضافه کنید.
.btn { display: block; background-color: var(--primary-color); color: var(--white); text-align: center; padding: 0.6rem 1.4rem; font-size: 1rem; font-weight: 500; border-radius: 5px; } .icon { padding: 0.5rem; background-color: var(--light-grey); border-radius: 10px; } .logo { margin-right: 1.5rem; } #nav-menu { border-bottom: var(--border); } .container { display: flex; align-items: center; justify-content: space-between; max-width: 1600px; margin: 0 auto; column-gap: 2rem; height: 90px; padding: 1.2rem 3rem; }
اکنون که این استایل اولیه را از سر راه برداشته اید، می توانید روی استایل دادن به خود نوار پیمایش اصلی تمرکز کنید.
در اینجا نشانه گذاری برای استایل دادن به محفظه نوار پیمایش آمده است:
.menu { position: relative; background: var(--white); } .menu-bar li:first-child .dropdown { flex-direction: initial; min-width: 480px; } .menu-bar li:first-child ul:nth-child(1) { border-right: var(--border); } .menu-bar li:nth-child(n + 2) ul:nth-child(1) { border-bottom: var(--border); } .menu-bar .dropdown-link-title { font-weight: 600; } .menu-bar .nav-link { font-size: 1rem; font-weight: 500; letter-spacing: -0.6px; padding: 0.3rem; min-width: 60px; margin: 0 0.6rem; } .menu-bar .nav-link:hover, .dropdown-link:hover { color: var(--primary-color); } .nav-start, .nav-end, .menu-bar, .right-container, .right-container .search { display: flex; align-items: center; }
علاوه بر حالت دادن به منوی کشویی، با استفاده از ترکیبی از آپشن های visibility
و opacity
پنهان میشود. ایده این است که منو فقط زمانی نشان داده شود که روی دکمه فردی کلیک شده باشد.
.dropdown { display: flex; flex-direction: column; min-width: 230px; background-color: var(--white); border-radius: 10px; position: absolute; top: 36px; z-index: 1; visibility: hidden; opacity: 0; transform: scale(0.97) translateX(-5px); transition: 0.1s ease-in-out; box-shadow: var(--shadow); } .dropdown.active { visibility: visible; opacity: 1; transform: scale(1) translateX(5px); } .dropdown ul { display: flex; flex-direction: column; gap: 0.5rem; padding: 1.2rem; font-size: 0.95rem; } .dropdown-btn { display: flex; align-items: center; justify-content: space-between; gap: 0.15rem; } .dropdown-link { display: flex; gap: 0.5rem; padding: 0.5rem 0; border-radius: 7px; transition: 0.1s ease-in-out; } .dropdown-link p { font-size: 0.8rem; color: var(--medium-grey); }
بعداً، منو را می توان با بازگرداندن ویژگی های visibility
و opacity
به حالت پیش فرض با استفاده از کلاس active
تغییر داد. اما ما این کار را از طریق جاوا اسکریپت انجام خواهیم داد.
اگر ترجیح می دهید منو به طور کامل مخفی شود، ویژگی های opacity
و visibility
را با display: none;
. اگرچه این ویژگی با استفاده از Transition در CSS قابل انیمیشن نیست .
سپس، استایل ورودی، دکمه و تصویر نمایه جستجو را اضافه کنید و سپس دکمه همبرگر را روی صفحههای دسکتاپ پنهان کنید.
.right-container { display: flex; align-items: center; column-gap: 1rem; } .right-container .search { position: relative; } .right-container img { border-radius: 50%; } .search input { background-color: var(--ash); border: none; border-radius: 6px; padding: 0.7rem; padding-left: 2.4rem; font-size: 16px; width: 100%; border: var(--border); } .search .search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); opacity: 0.6; } #hamburger { display: none; padding: 0.1rem; margin-left: 1rem; font-size: 1.9rem; }
در اینجا باید به نظر برسد:

برای تکمیل استایل، استایل درخواست رسانه را اضافه کنید:
@media (max-width: 1100px) { #hamburger { display: block; } .container { padding: 1.2rem; } .menu { display: none; position: absolute; top: 87px; left: 0; min-height: 100vh; width: 100vw; } .menu-bar li:first-child ul:nth-child(1) { border-right: none; border-bottom: var(--border); } .dropdown { display: none; min-width: 100%; border: none !important; border-radius: 5px; position: static; top: 0; left: 0; visibility: visible; opacity: 1; transform: none; box-shadow: none; } .menu.show, .dropdown.active { display: block; } .dropdown ul { padding-left: 0.3rem; } .menu-bar { display: flex; flex-direction: column; align-items: stretch; row-gap: 1rem; padding: 1rem; } .menu-bar .nav-link { display: flex; justify-content: space-between; width: 100%; font-weight: 600; font-size: 1.2rem; margin: 0; } .menu-bar > li:not(:last-child) { padding-bottom: 0.5rem; border-bottom: var(--border); } } @media (max-width: 600px) { .right-container { display: none; } }
اول، این عناصر را مرتب می کند و مهمتر از همه، کلاس hamburger
را هدف قرار می دهد و آن را پنهان می کند. اکنون در صفحه نمایش تبلت و موبایل، نوار پیمایش پاسخگو است و دکمه همبرگر قابل مشاهده است.

این یک ظاهر طراحی نوار ناوبری را کامل می کند. بیایید در بخش بعدی روی عملکرد کار کنیم.
مرحله ۳ - قابلیت جاوا اسکریپت را اضافه کنید
برای عملکرد جاوا اسکریپت، ما بر روی دسته های زیر تمرکز خواهیم کرد:
تغییر حالت مشاهده منوی کشویی
بستن منوی کشویی
تغییر حالت مشاهده منوی همبرگر
تغییر ویژگی aria-expanded
ابتدا کلاس های خود را با استفاده از روش querySelector
DOM انتخاب کنید و آنها را در متغیرهایی ذخیره کنید تا قابل استفاده مجدد باشند.
// script.js const dropdownBtn = document.querySelectorAll(".dropdown-btn"); const dropdown = document.querySelectorAll(".dropdown"); const hamburgerBtn = document.getElementById("hamburger"); const navMenu = document.querySelector(".menu"); const links = document.querySelectorAll(".dropdown a");
سپس توابع زیر را در کد خود اضافه کنید. کاربرد آنها را کمی بعد توضیح خواهم داد.
function setAriaExpandedFalse() { dropdownBtn.forEach((btn) => btn.setAttribute("aria-expanded", "false")); } function closeDropdownMenu() { dropdown.forEach((drop) => { drop.classList.remove("active"); drop.addEventListener("click", (e) => e.stopPropagation()); }); } function toggleHamburger() { navMenu.classList.toggle("show"); }
مرحله بعدی دریافت شناسه منوی کشویی است. از آنجایی که دو منوی کشویی وجود دارد، مقدار بر روی دکمه کشویی کلیک می شود.
برای دریافت شناسه، از ویژگی dataset
استفاده میکنید و سپس مقدار را در متغیر خودش ذخیره میکنید.
dropdownBtn.forEach((btn) => { btn.addEventListener("click", function (e) { const dropdownIndex = e.currentTarget.dataset.dropdown; const dropdownElement = document.getElementById(dropdownIndex); console.log(dropdownElement); }); });
برای شکستن این قطعه:
متد forEach
از میان مجموعه دکمه ها حلقه می زند
متد addEventListener()
یک رویداد کلیک را به هر دکمه متصل می کند
ویژگی currentTarget.dataset
کشویی فعلی دکمه کلیک شده را واکشی می کند.
هر یک از شناسه ها برای هدف قرار دادن عنصر کشویی مربوطه استفاده می شود
این بدان معنی است که وقتی روی دکمه با مجموعه داده dropdown1
کلیک می شود، عنصر div
با شناسه dropdown1
در کنسول ثبت می شود و برعکس برای دکمه dropdown2
.

اکنون که شناسه عنصر کشویی را در متغیری به نام dropdownElement
ذخیره کرده اید، تغییر منو بسیار آسان است. با هدف قرار دادن این متغیر، می توانید کلاس active
را در هر عنصر کشویی تغییر دهید.
dropdownBtn.forEach((btn) => { btn.addEventListener("click", function (e) { const dropdownIndex = e.currentTarget.dataset.dropdown; const dropdownElement = document.getElementById(dropdownIndex); dropdownElement.classList.toggle("active"); dropdown.forEach((drop) => { if (drop.id !== btn.dataset["dropdown"]) { drop.classList.remove("active"); } }); e.stopPropagation(); }); });
علاوه بر جابجایی منوی کشویی، یک شرط اضافه کردیم تا تحلیل کنیم آیا شناسه عنصر کشویی فعلی با دکمه فعال مطابقت دارد یا خیر. این اطمینان حاصل می کند که فقط یک عنصر کشویی در یک زمان گسترش می یابد.

تغییر ویژگی آریا گسترش یافته
ویژگی aria-expanded
به فنآوریهای کمکی اجازه میدهد تا اعلام کنند که آیا یک منوی تعاملی گسترش یافته یا جمعشده است. برای تغییر این ویژگی، این کد را در بلوک کد btn
در زیر e.stopPropagation()
وارد کنید:
btn.setAttribute( "aria-expanded", btn.getAttribute("aria-expanded") === "false" ? "true" : "false" );
اکنون هر زمان که منوی کشویی قابل مشاهده است، ویژگی aria-expanded
روی true و وقتی جمع شود روی false تنظیم می شود.

تا کنون تنها زمانی که دکمهها کلیک میشوند، فهرست کشویی فرو میرود. موارد دیگری که باید جمع شود عبارتند از:
هنگامی که پیوندهای داخل منوی کشویی کلیک می شوند
وقتی کلید ESC را می زنید
هنگامی که روی بدنه سند کلیک می کنید - اساساً خارج از محفظه کشویی.
با فراخوانی توابع ایجاد شده قبلی، closeDropdownMenu
و setAriaExpandedFalse
، منوی کشویی را می توان جمع کرد و ویژگی aria-expanded
را روی false تنظیم کرد.
// close dropdown menu when the dropdown links are clicked links.forEach((link) => link.addEventListener("click", () => { closeDropdownMenu(); setAriaExpandedFalse(); }) ); // close dropdown menu when you click on the document body document.documentElement.addEventListener("click", () => { closeDropdownMenu(); setAriaExpandedFalse(); }); // close dropdown when the escape key is pressed document.addEventListener("keydown", (e) => { if (e.key === "Escape") { closeDropdownMenu(); setAriaExpandedFalse(); } });
در اینجا خروجی حاصل آمده است:

برای مشاهده نوار پیمایش در صفحه نمایش تبلت و موبایل، تابع toggleHamburger
را به عنوان یک تماس بر روی دکمه همبرگر وصل کنید و سپس عملکرد را در داخل بلوک کد links
فراخوانی کنید.
links.forEach((link) => link.addEventListener("click", () => { closeDropdownMenu(); setAriaExpandedFalse(); toggleHamburger(); }) );
hamburgerBtn.addEventListener("click", toggleHamburger);
این کار اساساً کلاس دیگری به نام show
تغییر میدهد که کنترلها نوار ناوبری را نشان میدهند یا آن را پنهان میکنند.
در اینجا خروجی نهایی است:

شما می توانید منوهای کشویی بیشتری را با جایگزین کردن هر یک از موارد فهرست با پیوندی به منوی دارای دکمه و منوی کشویی اضافه کنید. برای اینکه کار کند، حتما موارد زیر را به روز کنید:
شناسه کشویی با توجه به تعداد منوهایی که نیاز دارید. به عنوان مثال، منوی سوم دارای شناسه dropdown3
خواهد بود
این دکمه دارای مقدار data-dropdown
آن بر روی dropdown3
خواهد بود
در اینجا یک مثال است که پیوند Jobs را به یک منوی کشویی تبدیل می کند.
قبل از:
<li><a class="nav-link" href="/">Jobs</a></li>
بعد از:
<li> <button class="nav-link dropdown-btn" data-dropdown="dropdown3" aria-haspopup="true" aria-expanded="false" aria-label="jobs" > Jobs <i class="bx bx-chevron-down" aria-hidden="true"></i> </button> <div id="dropdown3" class="dropdown"> <ul role="menu"> <li><span class="dropdown-link-title">Software</span></li> <li role="menuitem"> <a class="dropdown-link" href="#frontend">Frontend</a> </li> <li role="menuitem"> <a class="dropdown-link" href="#backend">Backend</a> </li> <li role="menuitem"> <a class="dropdown-link" href="#ai-ml">AI/ML</a> </li> <li role="menuitem"> <a class="dropdown-link" href="#mobile-dev">Mobile Development</a> </li> </ul> <ul role="menu"> <li> <span class="dropdown-link-title">Others</span> </li> <li role="menuitem"> <a class="dropdown-link" href="#ui-ux">UI/UX</a> </li> <li role="menuitem"> <a class="dropdown-link" href="#writing">Technical Writing</a> </li> </ul> </div> </li>
در اینجا نتیجه نهایی است:

پس از این فرآیند، می توانید هر تعداد منوی کشویی را که می خواهید اضافه کنید.
و با این کار، شما با موفقیت یک نوار ناوبری پاسخگو با منوهای کشویی فقط با استفاده از HTML، CSS و جاوا اسکریپت ساخته اید. شما همچنین یاد گرفتید که چگونه با استفاده از چند ویژگی aria از جمله ویژگی aria-expanded
منو را در دسترس قرار دهید.
در اینجا فایل کدپن برای آزمایش این نوار پیمایش در عمل آمده است:
با استفاده از این لینک فایل های کد را از GitHub دریافت کنید
نتیجه
من صمیمانه امیدوارم که این پست برای شما جالب یا مفید بوده باشد. اگر این کار را کردید، لطفا با دوستان خود به اشتراک بگذارید یا در وبلاگ من مشترک شوید تا هیچ پست بعدی را از دست ندهید. با تشکر برای خواندن.