בניית הניווט הראשי לאתר

במדריך הזה נסביר איך ליצור ניווט ראשי נגיש באתר. בקורס הזה תלמדו על HTML סמנטי, על נגישות ועל האופן שבו שימוש במאפייני ARIA יכול לפעמים להזיק יותר מאשר להועיל.

Manuel Matuzović
Manuel Matuzović

יש הרבה דרכים שונות לבנות את תפריט הניווט הראשי של אתר, מבחינת העיצוב, הפונקציונליות, הרכיבים הבסיסיים של ה-Markup והמידע הסמנטי. אם ההטמעה מינימליסטית מדי, היא תעמוד בדרישות של רוב האנשים, אבל יכול להיות שחוויית המשתמש (UX) לא תהיה טובה. אם האתר יהיה מורכב מדי, הוא עלול לבלבל את המשתמשים או אפילו למנוע מהם לגשת אליו בכלל.

ברוב האתרים, כדאי ליצור משהו שלא פשוט מדי ולא מסובך מדי.

בנייה בשכבות

במדריך הזה נתחיל בהגדרה בסיסית ונוסיף תכונות בשכבות, עד שנגיע לנקודה שבה נוכל לספק מספיק מידע, עיצוב ופונקציונליות כדי לרצות את רוב המשתמשים. כדי לעשות זאת, צריך להשתמש בעקרון השיפור ההדרגתי, שלפיו מתחילים עם הפתרון הבסיסי והחזק ביותר ומוסיפים בהדרגה שכבות של פונקציונליות. אם שכבה אחת לא תפעל מסיבה כלשהי, הניווט עדיין יפעל כי הוא יחזור בצורה חלקה לשכבה הבסיסית.

המבנה הבסיסי

כדי ליצור ניווט בסיסי, צריך שני דברים: רכיבי <a> וכמה שורות של CSS כדי לשפר את העיצוב והפריסה שמוגדרים כברירת מחדל של הקישורים.

<a href="/home">Home</a>
<a href="/about-us">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>
/* Define variables for your colors */
:root {
  --color-shades-dark: rgb(25, 25, 25);
}

/* Use the alternative box model
Details: <https://web.dev/learn/css/box-model/> */
*{
  box-sizing: border-box;
}

/* Basic font styling */
body {
  font-family: Segoe UI, system-ui, -apple-system, sans-serif;
  font-size: 1.6rem;
}

/* Link styling */
a {
  --text-color: var(--color-shades-dark);
  border-block-end: 3px solid var(--border-color, transparent);
  color: var(--text-color);
  display: inline-block;
  margin-block-end: 0.5rem; /* See note at the bottom of this chapter */
  margin-inline-end: 0.5rem;
  padding: 0.1rem;
  text-decoration: none;
}

/* Change the border-color on :hover and :focus */
a:where(:hover, :focus) {
  --border-color: var(--text-color);
}
שלב 1: HTML ו-CSS בסיסיים ב-CodePen

השיטה הזו מתאימה לרוב המשתמשים, לא משנה איך הם ניגשים לאתר. אפשר לנווט באמצעות עכבר, מקלדת, מכשיר מגע או קורא מסך, אבל יש מקום לשיפור. כדי לשפר את חוויית השימוש, אפשר להרחיב את התבנית הבסיסית הזו עם פונקציונליות ומידע נוספים.

אתם יכולים לבצע את הפעולות הבאות:

  • מדגישים את הדף הפעיל.
  • להכריז על מספר הפריטים למשתמשים עם קורא מסך.
  • מוסיפים ציון דרך ומאפשרים למשתמשים בקורא מסך לגשת לניווט ישירות באמצעות קיצור דרך.
  • הסתרת הניווט בחלונות צפייה צרים.
  • שיפור העיצוב של המיקוד.

הדגשת הדף הפעיל

כדי להדגיש את הדף הפעיל, אפשר להוסיף סיווג לקישור המתאים.

<a href="/about-us" class="active-page">About us</a>

הבעיה בגישה הזו היא שהיא מעבירה את המידע על הקישור הפעיל באופן חזותי בלבד. משתמש עיוור עם קורא מסך לא הצליח להבחין בין הדף הפעיל לדפים אחרים. למרבה המזל, תקן Accessible Rich Internet Applications‏ (ARIA) מציע דרך להעביר את המידע הזה גם באופן סמנטי. משתמשים במאפיין ובערך aria-current="page" במקום בכיתה.

aria-current (מצב) מציין את האלמנט שמייצג את הפריט הנוכחי בתוך מאגר או קבוצה של אלמנטים קשורים. אסימון דף שמשמש לציון קישור בתוך קבוצה של קישורי חלוקה לדפים, כאשר העיצוב החזותי של הקישור מייצג את הדף שמוצג כרגע. [Accessible Rich Internet Applications ‏ (WAI-ARIA) 1.1](https://www.w3.org/TR/wai-aria/#aria-current)

בעזרת המאפיין הנוסף, קורא המסך מכריז עכשיו משהו כמו 'הדף הנוכחי, קישור, מידע עלינו' במקום רק 'קישור, מידע עלינו'.

<a href="/about-us" aria-current="page" class="active-page">About us</a>

תופעת לוואי נוחה היא שאפשר להשתמש במאפיין כדי לבחור את הקישור הפעיל ב-CSS, וכך הכיתה active-page הופכת ללא רלוונטית.

<a href="/home">Home</a>
<a href="/about-us" aria-current="page">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>
/* Change border-color and color for the active page */
[aria-current="page"] {
  --border-color: var(--color-highlight);
  --text-color: var(--color-highlight);
}
שלב 2: מדגישים את הדף הפעיל ב-CodePen

הקראה של מספר הפריטים

משתמשים שרואים יכולים לראות מהתפריט הניווט שיש בו רק ארבעה קישורים. משתמש עיוור בקורא מסך לא יכול לקבל את המידע הזה במהירות כזו. יכול להיות שהם יצטרכו לעבור על כל רשימת הקישורים. יכול להיות שהבעיה הזו לא תהיה רלוונטית אם הרשימה קצרה כמו בדוגמה הזו, אבל אם היא מכילה 40 קישורים, המשימה הזו יכולה להיות מסורבלת. אם משתמש בקורא מסך יודע מראש שהניווט מכיל הרבה קישורים, יכול להיות שהוא יחליט להשתמש בדרך ניווט אחרת ויעילה יותר, כמו חיפוש באתר.
דרך טובה להציג מראש את מספר הפריטים היא להכניס כל קישור לפריט רשימה (<li>) שמוטמע ברשימה לא ממוינת (<ul>).

<ul>
  <li>
     <a href="/home">Home</a>
  </li>
  <li>
    <a href="/about-us" aria-current="page">About us</a>
  </li>
  <li>
    <a href="/pricing">Pricing</a>
  </li>
  <li>
    <a href="/contact">Contact</a>
  </li>
</ul>

כשמשתמש בקורא מסך מוצא את הרשימה, התוכנה שלו תקריא משהו כמו 'רשימה, 4 פריטים'.

הנה הדגמה של הניווט בקורא המסך NVDA ב-Windows.

עכשיו צריך לשנות את הסגנון כך שייראה כמו קודם.

/* Remove the default list styling and create a flexible layout for the list */
ul {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Basic link styling */
a {
  --text-color: var(--color-shades-dark);

  border-block-end: 3px solid var(--border-color, transparent);
  color: var(--text-color);
  padding: 0.1rem;
  text-decoration: none;
}

לשימוש ברשימות יכולים להיות יתרונות רבים למשתמשים בקורא מסך:

  • הם יכולים לקבל את המספר הכולל של הפריטים לפני שהם יוצרים איתם אינטראקציה.
  • הם עשויים להשתמש במקשי קיצור כדי לעבור מפריט לפריט ברשימה.
  • הם יכולים להשתמש בקיצורי דרך כדי לעבור מרשימת פריטים לרשימת פריטים אחרת.
  • קורא המסך עשוי להכריז על המיקום של הפריט הנוכחי (לדוגמה, 'פריט ברשימת פריטים, שני מתוך ארבעה').

בנוסף, אם הדף מוצג ללא CSS, הקישורים מוצגים ברשימה כקבוצה עקבית של פריטים במקום פשוט כרריג של קישורים.

פרט חשוב לגבי VoiceOver ב-Safari הוא שאתם מפסידים את כל היתרונות האלה כשמגדירים את list-style: none. זהו מצב מתוכנן. צוות WebKit החליט להסיר את הסמנטיקה של רשימות, כשרשימה לא נראית כמו רשימה. בהתאם למורכבות הניווט, יכול להיות שזו בעיה ויכול להיות שלא. מצד אחד, עדיין אפשר להשתמש בניווט והבעיה משפיעה רק על VoiceOver ב-Safari. קורא המסך VoiceOver עם Chrome או Firefox עדיין מכריז על מספר הפריטים, וגם קוראי מסך אחרים, כמו NVDA. לעומת זאת, המידע הסמנטי יכול להיות שימושי מאוד במצבים מסוימים. כדי לקבל החלטה כזו, כדאי לבדוק את הניווט עם משתמשים אמיתיים בקורא מסך ולקבל מהם משוב. אם אתם רוצים ש-VoiceOver ב-Safari יפעל כמו כל קוראי המסך האחרים, תוכלו לעקוף את הבעיה על ידי הגדרת תפקיד הרשימה של ARIA באופן מפורש ב-<ul>. הפעולה הזו תחזיר את ההתנהגות למצב שהיה לפני הסרת סגנון הרשימה. מבחינה חזותית, הרשימה עדיין נראית אותו דבר.

<ul role="list">
  <li>
     <a href="/home">Home</a>
  </li>
  ...
</ul>
שלב 3: הצגת מספר הפריטים ב-CodePen

הוספת ציון דרך

בעזרת מעט מאמץ, ביצעת שיפורים משמעותיים למשתמשים בקורא מסך, אבל יש עוד דבר אחד שאפשר לעשות. מבחינה סמנטית, הניווט הוא עדיין רק רשימה של קישורים, וקשה להבין שזו הרשימה הספציפית שמשמשת לניווט הראשי באתר. כדי להפוך את הרשימה הרגילה הזו לרשימה לניווט, צריך לעטוף את <ul> ברכיב <nav>.

יש כמה יתרונות לשימוש ברכיב <nav>. חשוב לציין שקורא מסך מכריז משהו כמו 'ניווט' כשהמשתמש מקיים איתו אינטראקציה, והוא מוסיף ציון דרך לדף. ציוני דרך הם אזורים מיוחדים בדף, כמו <header>, ‏ <footer> או <main>, שקורא המסך יכול לקפוץ אליהם. כדאי להוסיף נקודות ציון לדף, כי הן מאפשרות למשתמשים בקורא מסך לגשת ישירות לאזורים חשובים בדף בלי צורך באינטראקציה עם שאר הדף. לדוגמה, אפשר לדלג מציון דרך אחד למשנהו על ידי לחיצה על המקש D ב-NVDA. ב-VoiceOver, אפשר להשתמש בבורר כדי לקבל רשימה של כל נקודות הציון בדף. לשם כך, מקישים על VO + U.

רשימה של ארבע נקודות ציון: באנר, ניווט, ראשי, פרטי תוכן.
הרוטור ב-VoiceOver עם רשימה של כל ציוני הדרך בדף.

ברשימה הזו מופיעים 4 מאפיינים עיקריים: באנר, שהוא הרכיב <header>, ניווט, שהוא הרכיב <nav>, ראשי, שהוא הרכיב <main> ופרטי תוכן, שהוא הרכיב <footer>. הרשימה הזו לא צריכה להיות ארוכה מדי. מומלץ לסמן רק חלקים קריטיים בממשק המשתמש בתור ציוני דרך, כמו חיפוש באתר, ניווט מקומי או חלוקה לדפים.

אם יש לכם ניווט באתר כולו, ניווט מקומי בדף חלוקה לדפים בדף אחד, יכול להיות שיהיו לכם גם 3 רכיבי <nav>. זה בסדר, אבל עכשיו יש שלושה ציוני דרך לניווט, והם נראים זהים מבחינה סמנטית. קשה להבדיל ביניהם, אלא אם אתם מכירים היטב את מבנה הדף.

תמונה שבה מוצגים שלושה ציוני דרך עם הכיתוב &#39;ניווט&#39;.
החוגה של VoiceOver עם רשימה של שלושה ציוני דרך לניווט ללא תוויות.

כדי להבדיל ביניהם, צריך לתייג אותם באמצעות aria-labelledby או aria-label.

<nav aria-label="Main">
    <ul>
      <li>
         <a href="/home">Home</a>
      </li>
      ...
  </ul>
</nav>
...
<nav aria-label="Select page">
    <ul>
      <li>
         <a href="/page-1">1</a>
      </li>
      ...
    </ul>
</nav>

אם התווית שבחרתם כבר קיימת במקום כלשהו בדף, תוכלו להשתמש ב-aria-labelledby במקום זאת ולהפנות לתווית הקיימת באמצעות המאפיין id.

<nav aria-labelledby="pagination_heading">
  <h2 id="pagination_heading">Select a page</h2>
  <ul>
    <li>
       <a href="/page-1">1</a>
    </li>
    ...
  </ul>
</nav>

תוויות תמציתיות מספיקות, אל תשתמשו בביטויים ארוכים מדי. מומלץ להשמיט ביטויים כמו 'ניווט' או 'תפריט', כי קורא המסך כבר מספק למשתמשים את המידע הזה.

ציוני דרך
הקריינות מקריאה את האפשרויות 'באנר', 'תפריט ניווט ראשי', 'ראשי', 'ניווט בדף', 'בחירת ניווט בדף' ו'פרטי תוכן'.
שלב 4: הוספת ציון דרך ב-CodePen

הסתרת הניווט בחלונות צפייה צרים

באופן אישי, אני לא אוהב להסתיר את הניווט הראשי בחלונות צפייה צרים, אבל אם רשימת הקישורים ארוכה מדי, אין מנוס מכך. במקרה כזה, במקום הרשימה, המשתמשים יראו לחצן עם הכיתוב 'תפריט' או סמל המבורגר או שילוב של שניהם. לחיצה על הלחצן מציגה ומסתירה את הרשימה. אם יש לכם ידע בסיסי ב-JavaScript וב-CSS, תוכלו לבצע את המשימה הזו, אבל יש כמה דברים שצריך לדאוג להם מבחינת חוויית המשתמש והנגישות.

  • צריך להסתיר את הרשימה באופן נגיש.
  • הניווט צריך להיות נגיש באמצעות מקלדת.
  • התפריט הניווט צריך להציג אם הוא גלוי או לא.

הוספת לחצן 'המבורגר'

מכיוון שאתם פועלים לפי העיקרון של שיפור הדרגתי, חשוב לוודא שהניווט עדיין פועל ומתקבל על הדעת גם כש-JavaScript מושבת.
הדבר הראשון שדרוש לניווט הוא לחצן המבורגר. יוצרים אותו ב-HTML ברכיב תבנית, מעתיקים אותו ב-JavaScript ומוסיפים אותו לתפריט הניווט.

דף שבו מוצג לחצן המבורגר.
תוצאה: במקום קישורים, בתצוגות חלון מצומצמות מוצג לחצן המבורגר בתפריט הניווט.
<nav id="mainnav">
  ...
</nav>

<template id="burger-template">
  <button type="button" aria-expanded="false" aria-label="Menu" aria-controls="mainnav">
    <svg width="24" height="24" aria-hidden="true">
      <path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z">
    </svg>
  </button>
</template>
  1. המאפיין aria-expanded מאפשר לתוכנה של קורא המסך לדעת אם הרכיב שהכפתור שולט בו מורחב או לא.
  2. aria-label נותן ללחצן שם נגיש, טקסט חלופי לסמל המבורגר.
  3. אתם מסתירים את <svg> מטכנולוגיה מסייעת באמצעות aria-hidden כי כבר יש לו תווית טקסט שסופקה על ידי aria-label.
  4. aria-controls מאפשר לטכנולוגיה מסייעת שתומכת במאפיין (לדוגמה, JAWS) לדעת איזה רכיב הלחצן שולט בו.
const nav = document.querySelector('#mainnav')
const list = nav.querySelector('ul');
const burgerClone = document.querySelector('#burger-template').content.cloneNode(true);
const button = burgerClone.querySelector('button');

// Toggle aria-expanded attribute
button.addEventListener('click', e => {
  // aria-expanded="true" signals that the menu is currently open
  const isOpen = button.getAttribute('aria-expanded') === "true"
  button.setAttribute('aria-expanded', !isOpen);
});

// Hide list on keydown Escape
nav.addEventListener('keyup', e => {
  if (e.code === 'Escape') {
    button.setAttribute('aria-expanded', false);
  }
});

// Add the button to the page
nav.insertBefore(burgerClone, list);
  1. נוח למשתמשים לסגור את חלון הניווט מתי שהם רוצים, למשל בלחיצה על מקש Escape.
  2. חשוב להשתמש ב-insertBefore במקום ב-appendChild כי הלחצן צריך להיות הרכיב הראשון בתפריט הניווט. אם משתמש עם מקלדת או קורא מסך לוחץ על Tab אחרי שהוא לוחץ על הלחצן, הוא מצפה שהמיקוד יעבור לפריט הראשון ברשימה. אם הלחצן מופיע אחרי הרשימה, זה לא יקרה.

בשלב הבא, מאפסים את סגנון ברירת המחדל של הלחצן ומוודאים שהוא גלוי רק בחלונות צפייה צרים.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
  }
}

/* Reset button styling */
button {
  all: unset;
  display: var(--nav-button-display, flex);
}
שלב 5: הוספת לחצן המבורגר ב-CodePen

הסתרת הרשימה

לפני שמסתירים את הרשימה, צריך למקם את התפריט ואת הרשימה ולקבוע את הסגנון שלהם כך שהפריסה תהיה אופטימלית לתצוגות חלון מצומצמות, אבל עדיין תיראה טוב במסכים גדולים יותר.
קודם כול, מסירים את <nav> מהזרימה הטבעית של הדף וממקמים אותו בפינה העליונה של אזור התצוגה.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }
}

nav {
  position: var(--nav-position, fixed);
  inset-block-start: 1rem;
  inset-inline-end: 1rem;
}

בשלב הבא, משנים את הפריסה במסכי צפייה צרים על ידי הוספת מאפיין מותאם אישית חדש (—-nav-list-layout). כברירת מחדל, הפריסה היא בעמודות, והיא עוברת לשורות במסכים גדולים יותר.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }

  ul {
    --nav-list-layout: row;
  }
}

ul {
  display: flex;
  flex-direction: var(--nav-list-layout, column);
  flex-wrap: wrap;
  gap: 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

הניווט אמור להיראות כך במסכי צפייה צרים.

הדף שבו מוצגת רשימת הניווט וכפתור ההמבורגר.
גם לחצן המבורגר וגם הרשימה ממוקמים בפינה העליונה של אזור התצוגה.

ברור שצריך להוסיף לרשימה קצת CSS. נזיז אותו לפינה העליונה, נגדיל אותו כך שייראה בכל המסך אנכית, ונוסיף לו background-color ו-box-shadow.

@media (min-width: 48em) {
  nav {
    --nav-button-display: none;
    --nav-position: static;
  }
  
  ul {
    --nav-list-layout: row;
    --nav-list-position: static;
    --nav-list-padding: 0;
    --nav-list-height: auto;
    --nav-list-width: 100%;
    --nav-list-shadow: none;
  }
}

ul {
  background: rgb(255, 255, 255);
  box-shadow: var(--nav-list-shadow, -5px 0 11px 0 rgb(0 0 0 / 0.2));
  display: flex;
  flex-direction: var(--nav-list-layout, column);
  flex-wrap: wrap;
  gap: 1rem;
  height: var(--nav-list-height, 100vh);
  list-style: none;
  margin: 0;
  padding: var(--nav-list-padding, 2rem);
  position: var(--nav-list-position, fixed);
  inset-block-start: 0; /* Logical property. Equivalent to top: 0; */
  inset-inline-end: 0; /* Logical property. Equivalent to right: 0; */
  width: var(--nav-list-width, min(22rem, 100vw));
}

button {
  all: unset;
  display: var(--nav-button-display, flex);
  position: relative;
  z-index: 1;
}

רשימת הפריטים אמורה להיראות בערך כך בחלונות צפייה צרים, יותר כמו סרגל צד מאשר רשימה פשוטה.

רשימת הניווט תיפתח.

לבסוף, מסתירים את הרשימה, מציגים אותה רק כשהמשתמש לוחץ על הלחצן פעם אחת ומסתירים אותה כשהוא לוחץ שוב. חשוב להסתיר רק את הרשימה ולא את כל תפריט הניווט, כי אם תסתירו את תפריט הניווט, תסתירו גם ציון דרך חשוב.

קודם הוספת לחצן לאירוע לחיצה כדי להחליף את הערך של המאפיין aria-expanded. אפשר להשתמש במידע הזה כתנאי להצגה והסתרה של הרשימה ב-CSS.

@media (min-width: 48em) {
  ul {
    --nav-list-visibility: visible;
  }
}

ul {
  visibility: var(--nav-list-visibility, visible);
}

/* Hide the list on narrow viewports, if it comes after an element with
   aria-expanded set to "false". */
[aria-expanded="false"] + ul {
  visibility: var(--nav-list-visibility, hidden);
}

חשוב להשתמש בהצהרת מאפיין כמו visibility: hidden או display: none במקום opacity: 0 או translateX(100%) כדי להסתיר את הרשימה. המאפיינים האלה מוודאים שלא ניתן להתמקד בקישורים כשהניווט מוסתר. שימוש ב-opacity או ב-translate יסיר את התוכן באופן חזותי, כך שהקישורים לא יהיו גלויים אבל עדיין יהיו נגישים באמצעות המקלדת. זה עלול לבלבל ולגרום לתסכול. שימוש ב-visibility או ב-display מסתיר את הרכיב באופן חזותי ולא מאפשר גישה אליו, כך שהוא מוסתר מכל המשתמשים.

שלב 6: הסתרת הרשימה

אנימציה של הרשימה

אם אתם תוהים למה כדאי להשתמש ב-visibility: hidden; במקום ב-display: none;, הסיבה היא שאפשר להוסיף אנימציה לסטטוס החשיפה. יש לו רק שני מצבים, hidden ו-visible, אבל אפשר לשלב אותו עם נכס אחר כמו transform או opacity כדי ליצור אפקט של החלקה או של דהייה. הקוד הזה לא יפעל עם display: none כי לא ניתן ליצור אנימציה של מאפיין התצוגה.

המעבר הבא ב-CSS opacity יוצר אפקט של מעבר הדרגתי לכניסה וליציאה.

ul {
  transition: opacity 0.6s linear, visibility 0.3s linear;
  visibility: var(--nav-list-visibility, visible);
}

[aria-expanded="false"] + ul {
  opacity: 0;
  visibility: var(--nav-list-visibility, hidden);
}

אם אתם רוצים להוסיף אנימציה לתנועה במקום זאת, כדאי לחשוב על עטיפה של המאפיין transition בשאילתת מדיה מסוג prefers-reduced-motion, כי אנימציות עלולות לגרום לבחילות, סחרחורת וכאבי ראש אצל משתמשים מסוימים.

ul {
  visibility: var(--nav-list-visibility, visible);
}

@media (prefers-reduced-motion: no-preference) {
  ul {
    transition: transform 0.6s cubic-bezier(.68,-0.55,.27,1.55), visibility 0.3s linear;
  }
}

[aria-expanded="false"] + ul {
  transform: var(--nav-list-transform, translateX(100%));
  visibility: var(--nav-list-visibility, hidden);
}

כך מוודאים שרק אנשים שאין להם העדפה לתנועה מופחתת יראו את האנימציה.

שלב 7: הוספת אנימציה לרשימה ב-CodePen

שיפור העיצוב של המיקוד

משתמשים במקלדת מסתמכים על סגנונות המיקוד של רכיבים כדי לנווט בדף. סגנונות ברירת המחדל של התמקדות טובים יותר מסגנונות התמקדות כלליים (מצב שמתרחש אם מגדירים את הערך outline: none), אבל שימוש בסגנונות התמקדות מותאמים אישית שגלויים יותר משפר את חוויית המשתמש.

כך נראים סגנונות המיקוד שמוגדרים כברירת מחדל בקישורים ב-Chrome 103.

קו מתאר כחול באורך 2 פיקסלים סביב קישור שמתמקדים בו ב-Chrome 103.

כדי לשפר את המצב, אפשר לספק סגנונות משלכם בצבעים משלכם. שימוש ב-:focus-visible במקום ב-:focus מאפשר לדפדפן להחליט מתי מתאים להציג סגנונות של התמקדות. סגנונות :focus יהיו גלויים לכולם, למשתמשים בעכבר, במקלדת ובמסך מגע, גם אם הם לא צריכים אותם. כשמשתמשים ב-:focus-visible, הדפדפן משתמש בהיגוריית פנימית כדי להחליט אם להציג אותם רק למשתמשים במקלדת או לכולם.

/* Remove the default :focus outline */
*:focus {
  outline: none;
}

/* Show a custom outline on :focus-visible */
*:focus-visible {
  outline: 2px solid var(--color-shades-dark);
  outline-offset: 4px;
}

תמיכה בדפדפנים ב-:focus-visible

Browser Support

  • Chrome: 86.
  • Edge: 86.
  • Firefox: 85.
  • Safari: 15.4.

Source

קו מתאר כהה בגודל 2 פיקסלים שגלוי בבירור עם רווח בתוכו.

יש דרכים שונות להדגיש פריטים כשהם ממוקדים. מומלץ להשתמש במאפיין outline כי הוא לא מפר את הפריסה, מה שעלול לקרות עם border, והוא פועל היטב עם מצב ניגודיות גבוהה ב-Windows. נכסים שלא פועלים טוב הם background-color או box-shadow, כי יכול להיות שהם לא יוצגו בכלל עם הגדרות ניגודיות מותאמות אישית.

אתר עם רקע כהה והדגש מודגש בסגול.
שלב 8: שיפור סגנונות המיקוד ב-CodePen

מעולה! יצרתם ניווט ראשי משופר באופן מתמשך, עשיר מבחינה סמנטית, נגיש ומתאים לניידים.

תמיד יש משהו שאפשר לשפר, למשל:

אם אתם זוכרים איך המאמר הזה התחיל, עם המטרה שהפתרון לא יהיה "פשוט מדי או מורכב מדי", זה המקום שבו אנחנו נמצאים עכשיו. עם זאת, אפשר להשקיע יותר מדי מאמץ בתכנון הניווט.

יש הבדל ברור בין ניווטים לבין תפריטים. ניווטים הם אוספים של קישורים לניווט במסמכים קשורים. תפריטים הם אוספים של פעולות שאפשר לבצע במסמך. לפעמים המשימות האלה חופפות. יכול להיות שברשימת הניווט יש גם לחצן שמבצע פעולה, כמו פתיחת חלון מודלי, או תפריט שבו פעולה אחת מובילה לדף אחר, כמו דף עזרה. במקרה כזה, חשוב לא לשלב בין תפקידים של ARIA, אלא לזהות את המטרה העיקרית של הרכיב ולבחור את הרכיב והתפקידים בהתאם.

לרכיב <nav> יש תפקיד ARIA משתמע של ניווט, שהוא מספיק כדי להעביר את המסר שהרכיב הוא רכיב ניווט, אבל לעיתים קרובות אפשר לראות באתרים גם שימוש ברכיבים menu, ‏ menubar ו-menuitem. לפעמים אנחנו משתמשים במונחים האלה באופן חלופי, ולכן נראה ששילוב שלהם יכול לשפר את החוויה של משתמשים שנעזרים בקורא מסך. לפני שנראה למה בדרך כלל זה לא המצב, נבחן את ההגדרה הרשמית של התפקידים האלה.

תפקיד הניווט

אוסף של אלמנטים לניווט (בדרך כלל קישורים) לניווט במסמך או במסמכים קשורים.

navigation (תפקיד) WAI-ARIA 1.1

תפקיד התפריט

תפריט הוא בדרך כלל רשימה של פעולות או פונקציות נפוצות שהמשתמש יכול להפעיל. התפקיד של התפריט מתאים כשרשימה של אפשרויות בתפריט מוצגת באופן דומה לתפריט באפליקציה למחשב.

menu (תפקיד) WAI-ARIA 1.1

התפקיד של סרגל התפריטים

הצגת תפריט שנשאר בדרך כלל גלוי, ובדרך כלל מוצג באופן אופקי. התפקיד menubar משמש ליצירת סרגל תפריטים דומה לזה שנמצא באפליקציות למחשב של Windows,‏ Mac ו-Gnome. שורת תפריט משמשת ליצירת קבוצה עקבית של פקודות נפוצות. צריך לוודא שהאינטראקציה עם שורת התפריטים דומה לאינטראקציה הרגילה עם שורת התפריטים בממשק משתמש גרפי במחשב.

menubar (תפקיד) WAI-ARIA 1.1

התפקיד menuitem

אפשרות בקבוצת אפשרויות שמכיל תפריט או סרגל תפריטים.

menuitem (תפקיד) WAI-ARIA 1.1

כאן המפרט ברור מאוד: צריך להשתמש בניווט כדי לנווט במסמך או במסמכים קשורים, ובתפריט רק כדי להציג רשימה של פעולות או פונקציות, בדומה לתפריטים באפליקציות למחשב. אם אתם לא מפתחים את הגרסה הבאה של Google Docs, סביר להניח שאתם לא צריכים אף אחד מהתפקידים בתפריט לניווט הראשי.

מתי כדאי להשתמש בתפריט?

השימוש העיקרי בפריטי התפריט הוא לא לניווט, אלא לביצוע פעולות. נניח שיש לכם רשימה או טבלה של נתונים, והמשתמשים יכולים לבצע פעולות מסוימות בכל פריט ברשימה. אפשר להוסיף לחצן לכל שורה ולהציג את הפעולות כשהמשתמשים לוחצים על הלחצן.

<ul>
  <li>
    Product 1

    <button aria-expanded="false" aria-controls="options1">Edit</button>

    <div role="menu" id="options1">
      <button role="menuitem">
        Duplicate
      </button>
      <button role="menuitem">
        Delete
      </button>
      <button role="menuitem">
        Disable
      </button>
    </div>
  </li>
  <li>
    Product 2
    ...
  </li>
</ul>

ההשלכות של שימוש בתפקידי תפריט

חשוב מאוד להשתמש בתפקידי התפריט האלה בצורה מושכלת, כי יכולים לקרות הרבה דברים לא טובים.

תפריטים מצפים למבנה DOM מסוים. menuitem חייב להיות פריט צאצא ישיר של menu. הקוד הבא עלול לשבש את ההתנהגות הסמנטית:

 <!-- Wrong, don't do this -->
<ul role="menu">
  <li>
    <a href="#" role="menuitem">Item 1</a>
  </li>
</ul>

משתמשים מנוסים מצפים שמקשי קיצור מסוימים יפעלו בתפריטים ובסרגל התפריטים. על סמך המדריך לשיטות כתיבת ARIA (APG), הדברים האלה כוללים:

  • מקישים על Enter ועל מקש הרווח כדי לבחור אפשרויות בתפריט.
  • מקשי החיצים בכל הכיוונים כדי לנווט בין הפריטים.
  • המקשים Home ו-End כדי להעביר את המיקוד לפריט הראשון או האחרון, בהתאמה.
  • a-z כדי להעביר את המיקוד לפריט התפריט הבא עם תווית שמתחילה בתו שהוקלד.
  • מקישים על Esc כדי לסגור את התפריט.

אם קורא מסך מזהה תפריט, יכול להיות שהתוכנה תשנה באופן אוטומטי את מצב הגלישה, וכך תאפשר להשתמש בקיצורי הדרך שצוינו למעלה. משתמשים לא מנוסים בקורא מסך לא יוכלו להשתמש בתפריט כי הם לא מכירים את מקשי הקיצור האלה או לא יודעים איך להשתמש בהם.

אותו הדבר לגבי משתמשי מקלדת שעשויים לצפות שיוכלו להשתמש ב-Shift וב-Shift + Tab.

יש הרבה דברים שצריך לקחת בחשבון כשאתם יוצרים תפריטים וסרגלי תפריטים, והשאלה הראשונה שצריך לשאול היא אם בכלל כדאי להשתמש בהם. כשאתם יוצרים אתר רגיל, רכיב הניווט עם רשימה וקישורים הוא כל מה שאתם צריכים. ההגדרה הזו כוללת גם אפליקציות אינטרנט או אפליקציות בדף יחיד (SPA). אין חשיבות לסטאק הבסיסי. אלא אם אתם מפתחים משהו שדומה מאוד לאפליקציה למחשב, כדאי להימנע מתפקידי תפריט.

מקורות מידע נוספים

תמונה ראשית (Hero) של Mick Haupt