در این آموزش، یک روش ساده و در عین حال موثر برای ایجاد یک منوی پاسخگوی خارج از بوم با 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
عنصر به شکل زیر خواهد بود:
در این مورد، ما موارد زیر را انجام خواهیم داد:
- عناصر مستقیم فرزند را به عنوان عناصر با موقعیت ثابت که ارتفاع پنجره را پوشش می دهند، مشخص کنید.
- از 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 پیکسل خواهد داشت.
- طرح ناوبری به افقی تغییر می کند.
- منو تمام صفحه خواهد بود و به طور پیش فرض خارج از صفحه است.
- با کلیک بر روی منو، پوشش بنر به خارج از صفحه به سمت راست منتقل می شود.
از طرف دیگر، نگه داشتن همپوشانی بنر همیشه روی صفحه و همپوشانی منو در هنگام مشاهده نیز یک گزینه است. املاک زیر که با شماره مشخص شده اند را کامنت کنید 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
نقش.
امیدوارم از نتیجه نهایی لذت برده باشید و از آن به عنوان الهام بخش برای ایجاد منوهای خارج از بوم حتی قدرتمندتر استفاده کنید. و البته، در صورت ساختن، فراموش نکنید که آنها را با ما به اشتراک بگذارید!