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

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

מנואל מטוזוביץ'
מנואל מטוזוביץ'

יש דרכים רבות ושונות לבנות את הניווט הראשי באתר מבחינת הסגנון, הפונקציונליות, הסימון והמידע הסמנטי הבסיסיים. אם ההטמעה מינימליסטית מדי, היא מתאימה לרוב האנשים, אבל יכול להיות שחוויית המשתמש (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 (מצב) מציין את הרכיב שמייצג את הפריט הנוכחי בתוך מאגר או קבוצה של רכיבים קשורים. אסימון דף המשמש לציון קישור בתוך קבוצה של קישורי עימוד, כאשר הקישור מעוצב באופן חזותי כדי לייצג את הדף הנוכחי שמוצג. [אפליקציות אינטרנט עשירות (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>

כשמשתמש של קורא מסך מוצא את הרשימה, התוכנה שלו מכריזה משהו כמו "list, 4 items".

זוהי הדגמה של הניווט עם קורא המסך 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. ב-Voice Over, אפשר להשתמש בחוגה כדי להציג את כל ציוני הדרך בדף על ידי הקשה על 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>

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

ציוני דרך
VoiceOver כולל את ציוני הדרך 'באנר', 'ניווט ראשי', 'ראשי', 'ניווט בדף', 'בחירת ניווט בדף' ו'מידע על תוכן'.
מציגים את שלב 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 בשאילתת מדיה מסוג העדפה לצמצום תנועה, כי אנימציות יכולות לגרום לבחילה, סחרחורות וכאבי ראש אצל חלק מהמשתמשים.

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

תמיכה בדפדפן

  • 86
  • 86
  • 85
  • 15.4

מקור

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

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

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

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

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

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

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

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

תפקיד הניווט

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

ניווט (תפקיד) WAI-ARIA 1.1

תפקיד התפריט

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

תפריט (תפקיד) WAI-ARIA 1.1

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

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

סרגל תפריט (תפקיד) WAI-ARIA 1.1

תפקיד התפריט

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

menuitem (role) 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 ועל מקש הרווח.
  • מקשי החיצים בכל הכיוונים כדי לנווט בין פריטים.
  • המקשים בית וסיום כדי להעביר את המיקוד לפריט הראשון או לפריט האחרון בהתאמה.
  • a-z כדי להעביר את המיקוד לפריט הבא בתפריט עם תווית שמתחילה בתו שהוקלד.
  • Esc כדי לסגור את התפריט.

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

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

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

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

תמונה ראשית (Hero) של מיק האופט