בקודלאב הזה תלמדו איך ליצור רכיב רספונסיבי של פריסת ניווט צדדית נשלפת באינטרנט. נבנה את הרכיב תוך כדי תנועה, נתחיל ב-HTML, אחר כך ב-CSS ואז ב-JavaScript.
במאמר בבלוג שלי יצירת רכיב של תפריט צד תוכלו לקרוא על התכונות של פלטפורמת האינטרנט של CSS שבחרתי כדי ליצור את הרכיב הזה.
הגדרה
- לוחצים על רמיקס לעריכה כדי לערוך את הפרויקט.
- פתיחת
app/index.html
.
HTML
קודם כול, צריך להבין את היסודות של הגדרת ה-HTML כדי שיהיה תוכן ותיבות לעבודה איתן.
מוסיפים את קוד ה-HTML הבא לתג <body>
.
<aside></aside>
<main></main>
הרכיב <aside>
מכיל את תפריט הניווט כרכיב משלים של <main>
, שבו נשמר התוכן של הדף הראשי.
בשלב הבא נמלא את הרכיבים הסמנטיים האלה בשאר תוכן הדף.
צריך להוסיף רכיב ניווט, קישורי ניווט מסוימים וקישור לסגירת האפשרות בתוך הרכיב <aside>
.
<aside>
<nav>
<h4>My</h4>
<a href="#">Dashboard</a>
<a href="#">Profile</a>
<a href="#">Preferences</a>
<a href="#">Archive</a>
<h4>Settings</h4>
<a href="#">Accessibility</a>
<a href="#">Theme</a>
<a href="#">Admin</a>
</nav>
<a href="#"></a>
</aside>
קישורים מתאימים מאוד לשימוש ברכיבי <nav>
, ורכיבי <nav>
מתאימים מאוד לסרגלי צד של <aside>
.
עם זאת, יש עוד מה שאנחנו יכולים לעשות כדי לשפר.
ברכיב התוכן הראשי, מוסיפים כותרת ומאמר כדי להכיל את תוכן הפריסה מבחינה סמנטית.
<main>
<header>
<a href="#sidenav-open" class="hamburger">
<svg viewBox="0 0 50 40">
<line x1="0" x2="100%" y1="10%" y2="10%" />
<line x1="0" x2="100%" y1="50%" y2="50%" />
<line x1="0" x2="100%" y1="90%" y2="90%" />
</svg>
</a>
<h1>Site Title</h1>
</header>
<article>
{put some placeholder content here}
</article>
</main>
בכותרת מופיע הקישור לפתיחת התפריט. לחצן הסגירה מופיע בחלונית הצדדית. בקרוב נציג ונסתיר רכיבים בהתאם לגודל אזור התצוגה.
ברכיב <article>
הדבקנו משפט placeholder. מחליפים את `` בתוכן משלכם, או מדביקים את הטקסט הבא:
<h2>Totam Header</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum consectetur, necessitatibus velit officia ut impedit veritatis temporibus soluta? Totam odit cupiditate facilis nisi sunt hic necessitatibus voluptatem nihil doloribus! Enim.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<h3>Subhead Totam Odit</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<h3>Subhead</h3>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fugit rerum, amet odio explicabo voluptas eos cum libero, ex esse quasi optio incidunt soluta eligendi labore error corrupti! Dolore, cupiditate porro.</p>
התוכן הזה ואורכו הם הגורמים לכך שאפשר יהיה לגלול בדף אם הוא חורג מגובה אזור התצוגה.
עד עכשיו הוספתם אלמנט צד עם תפריט ניווט, קישורים ודרך לסגור את תפריט הניווט הצדדי. הוספת גם כותרת, דרך לפתוח את הניווט הצדדי ומאמר לרכיב הראשי. זה כבר יהיה נקי, סמנטי נצחי, אבל נוכל להפוך אותו לנקי וברור יותר לכולם. הקישור הפתוח בניווט הצד יכול להיות מסומן בצורה ברורה יותר.
מוסיפים את המאפיינים title
ו-aria-label
לאלמנט הקישור הפתוח בכותרת:
<a href="#sidenav-open" class="hamburger">
<a href="#sidenav-open" title="Open Menu" aria-label="Open Menu" class="hamburger">
אפשר גם לסמן את סמל ה-SVG הפתוח בצורה ברורה יותר. מוסיפים את המאפיינים הבאים ל-SVG שבתוך רכיב הקישור הפתוח:
<svg viewBox="0 0 50 40">
<svg viewBox="0 0 50 40" role="presentation" focusable="false" aria-label="trigram for heaven symbol">
הקישור שסגור בסרגל הצד יכול להיות מסומן בצורה ברורה יותר.
מוסיפים את המאפיינים title
ו-aria-label
לאלמנט הקישור לסגירה של תפריט הצד:
<a href="#"></a>
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
CSS
עכשיו הגיע הזמן למקם את הרכיבים. התוכן הראשי ותפריט הצד הם צאצאים ישירים של התג <body>
, כך שזו נקודת התחלה טובה.
מוסיפים את הקוד הבא ב-CSS אל css/sidenav.css
כדי שרכיב <body>
יארגן את הצאצאים.
body {
display: grid;
grid: [stack] 1fr / min-content [stack] 1fr;
@media (max-width: 540px) {
& > :matches(aside, main) {
grid-area: stack;
}
}
}
למעשה, הפריסה הזו אומרת: יוצרים שורה בעלת שם stack
עם כל מה שרוצים, ושתי עמודות בשורה הזו, כשהעמודה השנייה נקראת גם stack
. צריך לקבוע את הגודל של העמודה הראשונה בהתאם לצורכי התוכן המינימליים שלה, והעמודה השנייה יכולה להכיל את שאר התוכן.
לאחר מכן, אם חלון הצפייה מוגבל ל-540px
או פחות, צריך להציב את תפריט הצד ואת רכיבי התוכן הראשי באותה שורה ובאותה עמודה, כך שהם יופיעו זה מעל זה בתצוגת רשת של 1x1.
על בסיס הפונקציונליות הזו של יצירת ערימות רספונסיביות, אנחנו יכולים עכשיו להשתמש במצב של סרגל כתובות ה-URL כדי להחליף את ההצגה ואת סגנון המעבר של תפריט הצד.
מעדכנים את הרכיב <aside>
בחזרה ב-app/index.html
:
<aside>
<aside id="sidenav-open">
כך ה-CSS יכול להתאים אלמנט ל-hash של כתובת ה-URL ביחד. הדבר חשוב לשימוש ב-:target
.
עכשיו המזהה של הרכיב יכול להתאים ל-hash של כתובת ה-URL שנקבע באמצעות תגי <a>
.
בנוסף, כדי לטרגט JavaScript בקלות רבה יותר, מוסיפים מזהי רכיבים מרכזיים ששולטים בסרגל הצד. קודם כול, מוסיפים מזהה לקישור הפתוח בסרגל הניווט הצדדי:
<a href="#sidenav-open" class="hamburger" title="Open Menu" aria-label="Open Menu">
<a href="#sidenav-open" id="sidenav-button" class="hamburger" title="Open Menu" aria-label="Open Menu">
בשלב הבא, מוסיפים מזהה לקישור הסגירה של סרגל הניווט הצדדי:
<a href="#" title="Close Menu" aria-label="Close Menu"></a>
<a href="#" id="sidenav-close" title="Close Menu" aria-label="Close Menu"></a>
זהו הסיכום של הפריסה הרספונסיבית של המאקרו <body>
, שמקשרת אותנו לסרגל כתובות ה-URL.
קדימה, נמשיך!
ל-<aside>
יש גם פריסה מסודרת. יש לו 2 רכיבי צאצא: <nav>
, שהוא הרכיב שנראה כמו נייר וזז החוצה, ואלמנט קישור <a>
סוגר שמגדיר את כתובת ה-URL כ-#
.
הקישור אינו נראה משמאל לקובץ הנייר, מחליק החוצה; כדי שאנשים יוכלו ללחוץ על הרכיב החזותי כדי לסגור אותו.
מוסיפים את הקוד הבא לקובץ ה-CSS ב-css/sidenav.css
:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
}
לדעתי, היחס והשמות היו נגיעות נהדרות כאן, שבו התצוגה בחלוקה לרשת יכולה לזהור ולתת למעצב הרבה שליטה.
בשלב הבא צריך להציג את התוכן הראשי בשכבת-על באופן מותנה ולשמר את המיקום שלי
באמצעות גלילה במסמך. זו עבודה מצוינת ל-position: sticky
ולחלק מ-overscroll-behavior
.
מוסיפים את הסגנונות הבאים לתפריט הצד:
#sidenav-open {
display: grid;
grid-template-columns: [nav] 2fr [escape] 1fr;
@media (max-width: 540px) {
position: sticky;
top: 0;
max-height: 100vh;
overflow: hidden auto;
overscroll-behavior: contain;
visibility: hidden; /* not keyboard accessible when closed */
}
}
הסגנונות האלה מבטיחים שסרגל הניווט הצדדי יהיה בגובה של אזור התצוגה, יתגלול אנכית ויכיל את סרגל הגלילה. חשוב מאוד לציין שהיא מסתירה את הרכיב. כברירת מחדל, כשחלון התצוגה הוא 540px
או קטן ממנו, תפריט הצד הזה מוסתר. אלא אם!
מוסיפים בורר מדומה מסוג :target
לרכיב #sidenav-open
:
#sidenav-open {
@media (max-width: 540px) {
&:target {
visibility: visible;
}
}
}
אם המזהה של האלמנט הזה זהה למזהה של סרגל כתובות ה-URL, מגדירים את visibility
כ-visible
. אפשר לפתוח את תפריט הצד אחרי גלילה בדף, או לנסות לגלול בדף כשתפריט הצד פתוח. מה דעתך?
מוסיפים את הקוד הבא לקובץ ה-CSS app/sidenav.css
:
#sidenav-button,
#sidenav-close {
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
user-select: none;
touch-action: manipulation;
@media (min-width: 540px) {
display: none;
}
}
הסגנונות האלה מגדירים את הלחצנים לפתוח ולסגור, את סגנונות הקשה והמגע שלהם, וגם מסתירים אותם כשחלונות התצוגה הם בגודל 540px
או יותר.
כדי להוסיף קצת עניין, נוסיף טרנספורמציות CSS עם נגישות הולמת.
מוסיפים את הקוד הבא לקובץ ה-CSS ב-css/sidenav.css
:
#sidenav-open {
--easeOutExpo: cubic-bezier(0.16, 1, 0.3, 1);
--duration: .6s;
...
@media (max-width: 540px) {
...
transform: translateX(-110vw);
will-change: transform;
transition:
transform var(--duration) var(--easeOutExpo),
visibility 0s linear var(--duration);
&:target {
visibility: visible;
transform: translateX(0);
transition: transform var(--duration) var(--easeOutExpo);
}
}
@media (prefers-reduced-motion: reduce) {
--duration: 1ms;
}
}
מוסיפים קצת JavaScript
המקש Escape
אמור לסגור את התפריט. מוסיפים את הקוד הבא ב-JS אל js/index.js
:
const sidenav = document.querySelector('#sidenav-open');
sidenav.addEventListener('keyup', e => {
if (e.code === 'Escape') {
document.location.hash = '';
}
});
הקוד הזה מקשיב לאירוע מפתח ברכיב התפריט הצדדי.
אם הערך הוא Escape
, הוא מגדיר את גיבוב כתובת ה-URL כריק, וכך מפעיל את המעבר של סרגל הניווט הצדדי החוצה.
החלק הבא של UX JS הוא ניהול המיקוד. אני רוצה שהפתיחה והסגירה יהיו קלות, ולכן אני מחכה עד שחלונית הניווט הצדדית מסיימת מעבר כלשהו, ואז בודק אותה מול גיבוב כתובת ה-URL כדי לקבוע אם היא פתוחה או סגורה. לאחר מכן השתמשתי ב-JavaScript כדי להגדיר את המיקוד בלחצן שמשלים עם הלחצן שעליו הם לחצו.
מוסיפים את הקוד הבא ב-JavaScript אל js/index.js
:
const closenav = document.querySelector('#sidenav-close');
const opennav = document.querySelector('#sidenav-button');
sidenav.addEventListener('transitionend', e => {
if (e.propertyName !== 'transform') {
return;
}
const isOpen = document.location.hash === '#sidenav-open';
isOpen
? closenav.focus()
: opennav.focus();
});
רוצה לנסות?
- כדי לראות תצוגה מקדימה של האתר, לוחצים על View App (הצגת האפליקציה) ואז על Fullscreen (מסך מלא).
סיכום
זה סיכום של הצרכים שלי עם הרכיב. אתם מוזמנים להשתמש בקוד הזה, לשפר אותו, להפעיל אותו באמצעות מצב JavaScript במקום כתובת ה-URL ובאופן כללי להפוך אותו לקוד שלכם. תמיד יש עוד דברים שאפשר להוסיף או תרחישים לדוגמה שאפשר להציג.
פותחים את css/brandnav.css
כדי לראות את הסגנונות הקשורים ללא פריסה שהחלתי על הרכיב הזה. לא הרגשתי שהיא חשובה לחבילת התכונות שבהן התמקמתי, וקיוויתי שהפרדה בין סגנונות לפריסה תעודד העתקה והדבקה. יכול להיות שיש עוד יותר למידה בשבילכם!
איך יוצרים רכיבים רספונסיביים של תפריט צד שנשלף החוצה? יוצא לך בעתיד יותר מ-1, למשל אחד בשני הצדדים? אשמח להציג את הפתרון שלך בסרטון ב-YouTube. חשוב לשלוח לי ציוץ או להגיב ב-YouTube עם הקוד שלך, זה יעזור לכולם.