در این آموزش، یک روش ساده و در عین حال موثر برای ایجاد یک منوی پاسخگوی خارج از بوم با HTML، CSS و جاوا اسکریپت را مرور خواهیم کرد.

برای دریافت ایده اولیه از آنچه که خواهیم ساخت، به نسخه ی نمایشی CodePen مربوطه نگاهی بیندازید (به نسخه بزرگتر برای مشاهده چگونگی تغییر طرح):

اطلاعات

این آموزش در درجه اول بر نحوه دسترسی کامل به منوی خارج از بوم تمرکز نمی کند، بنابراین مطمئناً این یک قدم بعدی معتبر برای قوی تر کردن آن خواهد بود.

1. با نشانه گذاری شروع کنید

نشانه گذاری ما از دو عنصر بسته بندی تشکیل شده است:

  • را .top-banner عنصر
  • را .top-nav عنصر

در اینجا کد HTML آمده است:

1
<section class="top-banner">
2
  <div class="top-banner-overlay">
3
    <!-- content here -->
4
  </div>
5
</section>
6
7
<nav class="top-nav">
8
  <div class="menu-wrapper">
9
    <!-- content here -->
10
  </div>
11
  <div class="fixed-menu">
12
    <!-- content here -->
13
  </div>
14
</nav>

2. بعد ما به مقداری CSS نیاز داریم

با آماده شدن نشانه‌گذاری، در ادامه مهم‌ترین سبک‌های مورد نیاز برای منو را بررسی می‌کنیم.

اطلاعات

به خاطر خوانایی، این کد CSS بهینه نشده است – متوجه ویژگی های تکراری خواهید شد که ممکن است بخواهید در نسخه خود حذف کنید.

سبک دادن به عنصر بالای بنر

این .top-banner عنصر به شکل زیر خواهد بود:

عنصر بالای بنر چگونه به نظر می رسدعنصر بالای بنر چگونه به نظر می رسدعنصر بالای بنر چگونه به نظر می رسد

در مورد سبک های آن، موارد زیر را انجام خواهیم داد:

  • عرض آن را برابر با عرض پنجره منهای عرض قرار دهید .fixed-menu عنصر
  • ارتفاع آن را برابر با ارتفاع پنجره قرار دهید.
  • آن را به عنوان یک ظرف انعطاف پذیر تعریف کنید. این باعث می شود که پوشش آن تمام قد والد را پوشش دهد.
  • از flexbox برای وسط عمودی محتوای پوشش استفاده کنید.

در اینجا سبک هایی وجود دارد که برای رسیدن به همه اینها به آن نیاز داریم:

1
/*CUSTOM VARIABLES HERE*/
2
3
.top-banner {
4
  position: relative;
5
  left: 150px;
6
  display: flex;
7
  width: calc(100% - 150px);
8
  height: 100vh;
9
  background: url(IMAGE_PATH) no-repeat center / cover;
10
}
11
12
.top-banner-overlay {
13
  display: flex;
14
  flex-direction: column;
15
  justify-content: center;
16
  width: 350px;
17
  padding: 20px;
18
  transition: all .7s;
19
  color: var(--white);
20
  background: rgba(0, 0, 0, .7);
21
}

یک ظاهر طراحی شده .top-nav عنصر

این .top-nav عنصر به شکل زیر خواهد بود:

چگونه عنصر top-nav به نظر می رسدچگونه عنصر top-nav به نظر می رسدچگونه عنصر top-nav به نظر می رسد

در این مورد، ما موارد زیر را انجام خواهیم داد:

  • عناصر مستقیم فرزند را به عنوان عناصر با موقعیت ثابت که ارتفاع پنجره را پوشش می دهند، مشخص کنید.
  • از flexbox برای تراز عمودی استفاده کنید .fixed-menu عنصر
  • پنهان کردن .menu-wrapper عنصر به طور پیش فرض برای انجام این کار، ما به آن ارزش خاصی مانند display: none. در واقع، ما از translate() عملکرد آن را به اندازه 200 پیکسل به سمت چپ منتقل کنید. به خاطر داشته باشید که عرض عنصر 350 پیکسل است، بنابراین بخشی از آن همچنان در قسمت دید قرار دارد. با این حال، قابل مشاهده نخواهد بود زیرا عنصر در زیر آن قرار دارد .fixed-menu عنصر
  • لیست منو را مخفی کنید

به سبک های CSS مربوطه در زیر نگاهی بیندازید:

1
/*CUSTOM VARIABLES HERE*/
2
3
.top-nav .menu-wrapper {
4
  position: fixed;
5
  top: 0;
6
  left: 0;
7
  bottom: 0;
8
  width: 350px;
9
  padding: 20px;
10
  transform: translateX(-200px);
11
  transition: transform .7s;
12
  background: var(--menu-color);
13
}
14
15
.top-nav .menu-wrapper .menu {
16
  opacity: 0;
17
  transition: opacity .4s;
18
}
19
20
.top-nav .fixed-menu {
21
  position: fixed;
22
  top: 0;
23
  left: 0;
24
  bottom: 0;
25
  display: flex;
26
  flex-direction: column;
27
  width: 150px;
28
  padding: 20px;
29
  background: var(--fixed-menu-color);
30
}

3. در حال حاضر برای برخی از جاوا اسکریپت

در این مرحله، از کدهای جاوا اسکریپت ساده برای دستکاری وضعیت منوی خارج از بوم استفاده می کنیم.

تغییر منو

ما می توانیم منو را به روش های زیر تغییر دهیم:

  • هر بار که روی آن کلیک می کنیم .menu-toggle دکمه، نمای منو تغییر خواهد کرد. اگر پنهان باشد، با یک جلوه کشویی زیبا ظاهر می‌شود و روکش هم‌زمان به سمت راست فشار داده می‌شود. به صورت اختیاری، ما می‌توانیم کارهای بیشتری را در این حالت انجام دهیم. در مثال خود، یک سایه کادر به آن اضافه می کنیم ::before شبه عنصر همپوشانی و با استفاده از یک افکت محو شدن، فهرست منو را آشکار کنید. برعکس، اگر منو قابل مشاهده باشد، با یک افکت کشویی ناپدید می شود و پوشش همزمان به سمت چپ فشار داده می شود.

  • یکی دیگر از راه های ممکن برای بستن منو از طریق .menu-close دکمه ای که بخشی از .menu-wrapper عنصر
  • به‌طور پیش‌فرض، می‌توانیم با فوکوس کردن دکمه‌های جابجایی و فشار دادن دکمه، منو را از طریق صفحه‌کلید تغییر دهیم. Enter یا Tab کلیدها همچنین سناریویی برای بستن منو با فشار دادن دکمه اضافه می کنیم Esc کلید

در اینجا کد جاوا اسکریپت است که این رفتار را پیاده سازی می کند:

1
const topNav = document.querySelector(".top-nav");
2
const menuToggle = topNav.querySelector(".menu-toggle");
3
const menuClose = topNav.querySelector(".menu-close");
4
const menuWrapper = topNav.querySelector(".menu-wrapper");
5
const topBannerOverlay = document.querySelector(".top-banner-overlay");
6
const isOpenedClass = "is-opened";
7
const isMovedClass = "is-moved";
8
9
menuToggle.addEventListener("click", () => {
10
  menuWrapper.classList.toggle(isOpenedClass);
11
  topBannerOverlay.classList.toggle(isMovedClass);
12
});
13
14
menuClose.addEventListener("click", () => {
15
  menuWrapper.classList.remove(isOpenedClass);
16
  topBannerOverlay.classList.remove(isMovedClass);
17
});
18
19
document.addEventListener("keydown", (e) => {
20
  if (e.key == 'Escape' && menuWrapper.classList.contains(isOpenedClass)) {
21
    menuClose.click();
22
  }  
23
});

و در زیر استایل های CSS مرتبط را پیدا خواهید کرد:

1
.top-banner-overlay.is-moved {
2
  transform: translateX(350px);
3
}
4
5
.top-banner-overlay.is-moved::before {
6
  content: "";
7
  position: absolute;
8
  top: 0;
9
  bottom: 0;
10
  right: 100%;
11
  width: 20px;
12
  box-shadow: 3px 0 10px rgba(0, 0, 0, .75);
13
}
14
15
.top-nav .menu-wrapper.is-opened {
16
  transform: translateX(150px);
17
}
18
19
.top-nav .menu-wrapper.is-opened .menu {
20
  opacity: 1;
21
  transition-delay: .6s;
22
}

4. پاسخگو شدن

در این مرحله، نحوه واکنش‌پذیری خارج از بوم را بررسی خواهیم کرد.

هنگامی که نمایشگر تا 900 پیکسل است:

  • بنر بالا دارای ارتفاعی برابر با ارتفاع پنجره منهای ارتفاع خواهد بود .fixed-menu عنصر
  • همپوشانی بنر بالا ارتفاع پنجره را نخواهد داشت – به صورت عمودی در مرکز بنر قرار می گیرد.
  • همچنین، هدر ثابت دیگر ارتفاع پنجره را نخواهد داشت. در واقع، ارتفاع ثابت 50 پیکسل خواهد داشت.
  • طرح ناوبری به افقی تغییر می کند.
  • منو تمام صفحه خواهد بود و به طور پیش فرض خارج از صفحه است.
  • با کلیک بر روی منو، پوشش بنر به خارج از صفحه به سمت راست منتقل می شود.

طرح بندی صفحه روی صفحه نمایش تا 900 پیکسلطرح بندی صفحه روی صفحه نمایش تا 900 پیکسلطرح بندی صفحه روی صفحه نمایش تا 900 پیکسل

حالت منوی بازحالت منوی بازحالت منوی باز

از طرف دیگر، نگه داشتن همپوشانی بنر همیشه روی صفحه و همپوشانی منو در هنگام مشاهده نیز یک گزینه است. املاک زیر که با شماره مشخص شده اند را کامنت کنید 2 و قلم را اجرا کنید تا تفاوت را ببینید.

از آنجایی که ما از رویکرد اول دسکتاپ استفاده می کنیم، اینها مهمترین سبک هایی هستند که باید اضافه یا بازنویسی کنیم:

1
@media (max-width: 900px) {
2
  body {
3
    font-size: 16px;
4
    overflow-x: hidden;
5
  }
6
7
  .top-banner {
8
    top: 50px;
9
    left: auto;
10
    width: 100%;
11
    height: calc(100vh - 50px);
12
    transform: none;
13
    align-items: center;
14
  }
15
  
16
  .top-banner-overlay {
17
    position: relative; /*2*/
18
    left: 0; /*2*/
19
    max-width: 100%;
20
  }
21
22
  .top-banner-overlay.is-moved {
23
    left: 100%; /*2*/
24
    transform: none;
25
  }
26
27
  .top-nav .menu-wrapper {
28
    width: 100%;
29
    transform: translateX(-100%);
30
    padding-top: 70px;
31
  }
32
33
  .top-nav .menu-wrapper.is-opened {
34
    transform: none;
35
  }
36
37
  .top-nav .menu-wrapper .menu-close {
38
    top: 70px;
39
  }
40
41
  .top-nav .fixed-menu {
42
    bottom: auto;
43
    flex-direction: row;
44
    align-items: center;
45
    width: 100%;
46
    height: 50px;
47
    padding: 0 20px;
48
  }
49
50
  .top-nav .fixed-menu .menu-toggle {
51
    margin: 0;
52
    order: 3;
53
  }
54
55
  .top-nav .socials {
56
    display: flex;
57
    margin-left: auto;
58
    margin-right: 20px;
59
  }
60
}

5. پاک کردن انتقال در تغییر اندازه پنجره

ما تقریباً تمام شده ایم! مشابه کاری که ما در آن انجام داده ایم یک آموزش خارج از بوم دیگر، بیایید یک تنظیم دیگر انجام دهیم: هر بار که اندازه پنجره مرورگر را تغییر می دهیم، همه انتقال ها را پاک می کنیم. به این ترتیب، در مرحله تغییر اندازه، قبل از بازگشت به موقعیت پیش‌فرض خارج از صفحه، برای لحظه‌ای از دیدن خارج از بوم اجتناب می‌کنیم.

این کد اضافی است که به آن نیاز داریم:

1
const body = document.body;
2
const noTransitionClass = "no-transition";
3
let resize;
4
5
window.addEventListener("resize", () => {
6
  body.classList.add(noTransitionClass);
7
  clearTimeout(resize);
8
  resize = setTimeout(() => {
9
    body.classList.remove(noTransitionClass);
10
  }, 500);
11
});

و سبک مرتبط:

1
.no-transition * {
2
  transition: none !important;
3
}

نتیجه

همین است، مردمی! ما موفق شدیم یک منوی مفید خارج از بوم بسازیم که با کد نسبتاً ساده به خوبی در صفحه های مختلف ظاهر می شود. می‌توانید با افزودن ویژگی‌های اضافی ARIA مانند نسخه آزمایشی، آن را در دسترس‌تر کنید aria-labelledby صفت و dialog نقش.

امیدوارم از نتیجه نهایی لذت برده باشید و از آن به عنوان الهام بخش برای ایجاد منوهای خارج از بوم حتی قدرتمندتر استفاده کنید. و البته، در صورت ساختن، فراموش نکنید که آنها را با ما به اشتراک بگذارید!

تکنیک های خارج از بوم را بیشتر بیاموزید