บทแนะนำนี้จะอธิบายวิธีสร้างการนำทางหลักของเว็บไซต์ที่เข้าถึงได้ง่าย คุณจะได้เรียนรู้เกี่ยวกับ HTML เชิงความหมาย การช่วยเหลือพิเศษ และบางครั้งการใช้แอตทริบิวต์ ARIA อาจส่งผลเสียมากกว่าผลดีได้อย่างไร
การสร้างการนำทางหลักของเว็บไซต์ทำได้หลายวิธี ในแง่ของการจัดรูปแบบ ฟังก์ชันการทำงาน ตลอดจนมาร์กอัปพื้นฐานและข้อมูลความหมาย การติดตั้งใช้งานที่เรียบง่ายเกินไปอาจเหมาะสำหรับคนส่วนใหญ่ แต่ประสบการณ์ของผู้ใช้ (UX) อาจไม่ดีนัก เพราะมีความซับซ้อนมากเกินไป อาจทำให้ผู้ใช้สับสนหรือแม้แต่ทำให้ไม่สามารถเข้าถึงได้เลย
สำหรับเว็บไซต์ส่วนใหญ่ คุณควรสร้างสิ่งที่ไม่ง่ายหรือซับซ้อน
การสร้างเลเยอร์ทีละเลเยอร์
ในบทแนะนำนี้ คุณจะเริ่มต้นด้วยการตั้งค่าพื้นฐาน และเพิ่มเลเยอร์ของฟีเจอร์ทีละชั้นไปจนถึงจุดที่คุณให้ข้อมูล การจัดรูปแบบ และฟังก์ชันที่เพียงพอเพื่อสร้างความพอใจให้กับผู้ใช้ส่วนใหญ่ เพื่อให้คุณใช้ประโยชน์จากหลักการการเพิ่มประสิทธิภาพแบบก้าวหน้า ซึ่งระบุให้คุณเริ่มต้นด้วยโซลูชันขั้นพื้นฐานและมีประสิทธิภาพที่สุด จากนั้นจึงเพิ่มฟังก์ชันการทำงานทีละขั้น หากเลเยอร์ใดเลเยอร์หนึ่งไม่ทำงานด้วยเหตุผลบางอย่าง การนำทางจะยังคงใช้งานได้เนื่องจากเลเยอร์นั้นย้อนกลับไปที่เลเยอร์เบื้องหลังได้อย่างนุ่มนวล
โครงสร้างพื้นฐาน
สำหรับการนำทางพื้นฐาน คุณต้องมี 2 สิ่ง ได้แก่ องค์ประกอบ <a>
และ CSS 2-3 บรรทัดเพื่อปรับปรุงการจัดรูปแบบและเลย์เอาต์เริ่มต้นของลิงก์
<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);
}
วิธีการนี้เหมาะสำหรับผู้ใช้ส่วนใหญ่ ไม่ว่าผู้ใช้จะเข้าถึงไซต์ด้วยวิธีใด ไปยังส่วนต่างๆ ด้วยเมาส์ แป้นพิมพ์ อุปกรณ์ระบบสัมผัส หรือโปรแกรมอ่านหน้าจอได้ แต่ยังต้องปรับปรุงอีกเล็กน้อย คุณสามารถยกระดับประสบการณ์การใช้งานโดยขยายรูปแบบพื้นฐานนี้ด้วยฟังก์ชันการทำงานและข้อมูลเพิ่มเติม
คุณสามารถดำเนินการได้ดังนี้
- ไฮไลต์หน้าที่ใช้งานอยู่
- ประกาศจำนวนรายการไปยังผู้ใช้โปรแกรมอ่านหน้าจอ
- เพิ่มจุดสังเกตและอนุญาตให้ผู้ใช้โปรแกรมอ่านหน้าจอเข้าถึงการนำทางได้โดยตรงโดยใช้ทางลัด
- ซ่อนการนําทางในวิวพอร์ตแบบแคบ
- ปรับปรุงการจัดรูปแบบโฟกัส
ไฮไลต์หน้าที่ใช้งานอยู่
หากต้องการไฮไลต์หน้าที่ใช้งานอยู่ คุณสามารถเพิ่มชั้นเรียนในลิงก์ที่เกี่ยวข้องได้
<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);
}
ประกาศจำนวนรายการ
เมื่อดูที่การนำทาง ผู้ใช้ที่มองเห็นสามารถบอกได้ว่ามีลิงก์เพียงสี่ลิงก์เท่านั้น ผู้ใช้โปรแกรมอ่านหน้าจอที่ตาบอดอาจไม่ได้รับข้อมูลนี้อย่างรวดเร็ว โดยอาจต้องพยายามทำรายการลิงก์ทั้งหมดให้เสร็จเรียบร้อย กรณีนี้อาจไม่เป็นปัญหาหากรายการสั้นเหมือนในตัวอย่างนี้ แต่หากมีลิงก์ 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;
}
การใช้รายการจะมีข้อดีมากมายสำหรับผู้ใช้โปรแกรมอ่านหน้าจอ ดังนี้
- ผู้ใช้จะเห็นจำนวนรายการทั้งหมดก่อนที่จะโต้ตอบกับสินค้านั้นๆ
- ผู้ใช้อาจใช้แป้นพิมพ์ลัดเพื่อข้ามจากรายการหนึ่งไปยังอีกรายการ
- โดยอาจใช้แป้นพิมพ์ลัดเพื่อข้ามจากรายการหนึ่งไปยังอีกรายการ
- โปรแกรมอ่านหน้าจออาจอ่านดัชนีของรายการปัจจุบัน (เช่น "รายการ 2 จาก 4 รายการ")
ยิ่งไปกว่านั้น หากหน้าเว็บแสดงโดยไม่มี 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>
เพิ่มจุดสังเกต
คุณได้ทำการปรับปรุงที่ยอดเยี่ยมสำหรับผู้ใช้โปรแกรมอ่านหน้าจอโดยใช้ความพยายามเพียงเล็กน้อย แต่ยังมีอีก 1 สิ่งที่คุณสามารถทำได้ การนำทางยังคงเป็นเพียงรายการลิงก์เท่านั้น และยากที่จะบอกว่ารายการที่เจาะจงนี้เป็นการนำทางหลักของเว็บไซต์ของคุณ คุณสามารถเปลี่ยนรายการธรรมดานี้ให้เป็นรายการการนําทางได้ด้วยการรวม <ul>
ไว้ในองค์ประกอบ <nav>
การใช้องค์ประกอบ <nav>
มีข้อดีหลายอย่าง สิ่งที่น่าสังเกตคือ โปรแกรมอ่านหน้าจอจะอ่านออกเสียง เช่น "การนำทาง" เมื่อผู้ใช้โต้ตอบกับโปรแกรมดังกล่าวจะเพิ่มจุดสังเกตลงในหน้าเว็บ จุดสังเกตเป็นส่วนพิเศษในหน้าเว็บ เช่น <header>
, <footer>
หรือ <main>
ซึ่งโปรแกรมอ่านหน้าจอสามารถข้ามไป การมีจุดสังเกตในหน้าเว็บอาจเป็นประโยชน์เนื่องจากช่วยให้ผู้ใช้โปรแกรมอ่านหน้าจอเข้าถึงภูมิภาคที่สำคัญในหน้าเว็บได้โดยตรงโดยไม่ต้องโต้ตอบกับส่วนที่เหลือของหน้า เช่น คุณจะข้ามจากจุดสังเกตไปอีกจุดหนึ่งได้โดยกดปุ่ม D ใน NVDA ในเสียงบรรยาย คุณสามารถใช้โรเตอร์เพื่อแสดงจุดสังเกตทั้งหมดในหน้าเว็บได้โดยกด VO + U
![รายการจุดสังเกต 4 อย่าง ได้แก่ แบนเนอร์ การนำทาง ข้อมูลหลัก และข้อมูลเนื้อหา](https://web.dev/static/articles/website-navigation/image/a-list-four-landmarks-b-a1d2ac087daef.png?authuser=6&hl=th)
ในรายการนี้คุณจะเห็นจุดสังเกต 4 รายการ ได้แก่ แบนเนอร์ซึ่งเป็นองค์ประกอบ <header>
การนำทางคือ<nav>
หลัก องค์ประกอบ <main>
และข้อมูลเนื้อหาคือ<footer>
รายการนี้ไม่ควรยาวเกินไป คุณต้องการทำเครื่องหมายเฉพาะส่วนสำคัญๆ ของ UI ว่าเป็นจุดสังเกต เช่น การค้นหาเว็บไซต์ การนำทางในท้องถิ่น หรือการใส่เลขหน้า
หากมีการนําทางทั้งเว็บไซต์ การนําทางในพื้นที่สําหรับหน้าเว็บ และการใส่เลขหน้าในหน้าเดียว คุณอาจมีองค์ประกอบ <nav>
3 รายการได้อีกด้วย แต่ตอนนี้มีจุดสังเกตของการไปยังส่วนต่างๆ 3 แห่ง และมีความหมายเหมือนกันทั้งหมด ยากที่จะแยกความแตกต่างได้ เว้นแต่คุณจะรู้จักโครงสร้างของหน้าเว็บเป็นอย่างดี
![รูปภาพแสดงจุดสังเกต 3 แห่งซึ่งทั้งหมดพูดว่า "การนำทาง"](https://web.dev/static/articles/website-navigation/image/image-showing-three-landm-f3d5de4194a49.png?authuser=6&hl=th)
หากต้องการทำให้แยกความแตกต่างได้ คุณควรติดป้ายกำกับโดยใช้ 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>
ป้ายกำกับที่สั้นกระชับก็เพียงพอ แต่อย่าใช้คำมากเกินไป อย่าใช้นิพจน์ เช่น "การนำทาง" หรือ "เมนู" เนื่องจากโปรแกรมอ่านหน้าจอให้ข้อมูลนี้แก่ผู้ใช้อยู่แล้ว
![จุดสังเกต](https://web.dev/static/articles/website-navigation/image/landmarks-banner-main-52ee497db7028.png?authuser=6&hl=th)
ซ่อนการนำทางบนวิวพอร์ตแคบ
โดยส่วนตัวแล้ว ผมไม่ชอบการซ่อนการนำทางหลักในวิวพอร์ตแบบแคบ แต่ถ้ารายการลิงก์ยาวเกินไป จะไม่มีทางแก้ไขได้ ในกรณีนี้ แทนที่จะเห็นรายการ ผู้ใช้จะเห็นปุ่มที่มีป้ายกำกับว่า "เมนู" หรือไอคอนเบอร์เกอร์ หรือทั้ง 2 ปุ่มรวมกัน การคลิกปุ่มดังกล่าวจะแสดงและซ่อนรายการ หากคุณรู้เรื่อง JavaScript และ CSS พื้นฐาน ก็ถือว่านี่เป็นงานที่ทำได้ แต่ก็ยังมีอีกหลายอย่างที่คุณจะต้องจัดการในเรื่องของ UX และการช่วยเหลือพิเศษ
- คุณต้องซ่อนรายการในลักษณะที่เข้าถึงได้ง่าย
- การนำทางต้องเข้าถึงด้วยแป้นพิมพ์ได้
- การนำทางต้องสื่อสารไม่ว่าจะมองเห็นได้หรือไม่
การเพิ่มปุ่มเบอร์เกอร์
เนื่องจากคุณกำลังทำตามหลักการเพิ่มประสิทธิภาพแบบต่อเนื่อง คุณต้องการตรวจสอบว่าการนำทางยังคงทำงานได้และเหมาะสมแม้ว่าจะปิด JavaScript อยู่ก็ตาม
สิ่งแรกที่ต้องมีการนำทางคือปุ่มเบอร์เกอร์ คุณสร้างแท็ก HTML ในองค์ประกอบเทมเพลต โคลนใน JavaScript แล้วเพิ่มลงในการนำทาง
![หน้าแสดงปุ่มเบอร์เกอร์](https://web.dev/static/articles/website-navigation/image/a-page-displaying-burger-d1ef89aa72d22.png?authuser=6&hl=th)
<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>
- แอตทริบิวต์
aria-expanded
จะบอกซอฟต์แวร์โปรแกรมอ่านหน้าจอว่าองค์ประกอบที่ตัวควบคุมปุ่มขยายอยู่หรือไม่ aria-label
ตั้งชื่อปุ่มที่เรียกได้ว่าเป็นปุ่มที่เข้าถึงได้ง่าย ซึ่งเป็นทางเลือกข้อความแทนไอคอนเบอร์เกอร์- คุณซ่อน
<svg>
จากเทคโนโลยีความช่วยเหลือพิเศษที่ใช้aria-hidden
เนื่องจากอุปกรณ์มีป้ายกำกับข้อความจากaria-label
อยู่แล้ว 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);
- ผู้ใช้สามารถปิดการนำทางได้ทุกเมื่อที่ต้องการ เช่น การกดปุ่ม Escape
- คุณต้องใช้
insertBefore
แทนappendChild
เนื่องจากปุ่มควรเป็นองค์ประกอบแรกในการนําทาง หากผู้ใช้แป้นพิมพ์หรือโปรแกรมอ่านหน้าจอกด Tab หลังจากคลิกปุ่ม ผู้ใช้คาดหวังว่าจะต้องโฟกัสรายการแรกในลิสต์ แต่ถ้าปุ่มตามหลังรายการ ก็จะไม่เป็นเช่นนั้น
ถัดไป คุณรีเซ็ตการจัดรูปแบบเริ่มต้นของปุ่มและตรวจสอบว่าปุ่มจะปรากฏเฉพาะในวิวพอร์ตแคบๆ เท่านั้น
@media (min-width: 48em) {
nav {
--nav-button-display: none;
}
}
/* Reset button styling */
button {
all: unset;
display: var(--nav-button-display, flex);
}
กำลังซ่อนรายการ
ก่อนซ่อนรายการ ให้จัดตำแหน่งและจัดรูปแบบการนำทางและรายการเพื่อให้เลย์เอาต์เหมาะสมที่สุดสำหรับวิวพอร์ตแบบแคบ แต่ยังคงดูดีในหน้าจอขนาดใหญ่
ขั้นแรก นำ <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;
}
การนำทางของคุณควรมีลักษณะดังนี้ในวิวพอร์ตแคบๆ
![หน้าเว็บที่แสดงรายการการนำทางและปุ่มเบอร์เกอร์](https://web.dev/static/articles/website-navigation/image/the-page-showing-navigat-7d2e463c7f0d1.png?authuser=6&hl=th)
รายการดังกล่าวจำเป็นต้องมี 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;
}
รายการควรมีลักษณะดังนี้ในวิวพอร์ตแคบๆ ที่คล้ายกับแถบด้านข้างมากกว่ารายการแบบง่าย
![รายการการนำทางจะเปิดขึ้น](https://web.dev/static/articles/website-navigation/image/the-navigation-list-open-529d28567d05a.png?authuser=6&hl=th)
สุดท้าย ซ่อนรายการ โดยแสดงเฉพาะเมื่อผู้ใช้คลิกปุ่ม 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
จะซ่อนตำแหน่งและทำให้เข้าถึงไม่ได้ ดังนั้นจึงซ่อนไม่ให้ผู้ใช้ทุกคนเห็น
การทำให้รายการเคลื่อนไหว
หากคุณสงสัยว่าทําไมควรใช้ visibility: hidden;
มากกว่า display: none;
นั่นเป็นเพราะคุณทําให้การแสดงผลเคลื่อนไหวได้ ข้อความนี้มีเพียง 2 สถานะคือ hidden
และ visible
แต่คุณสามารถรวมกับพร็อพเพอร์ตี้อื่น เช่น transform
หรือ opacity
เพื่อสร้างเอฟเฟกต์สไลด์หรือเฟดอินได้ จะใช้กับจอแสดงผลไม่ได้: ไม่มี เนื่องจากคุณสมบัติการแสดงผลไม่สามารถเคลื่อนไหวได้
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);
}
ทำให้มั่นใจว่ามีเพียงผู้ที่ไม่อยากลดการเคลื่อนไหวเท่านั้นที่จะเห็นภาพเคลื่อนไหว
ปรับปรุงการจัดรูปแบบโฟกัส
ผู้ใช้แป้นพิมพ์จะใช้รูปแบบโฟกัสขององค์ประกอบเพื่อการวางแนวและการนำทางในหน้า รูปแบบโฟกัสเริ่มต้นดีกว่าไม่มีรูปแบบการโฟกัส (ซึ่งจะเกิดขึ้นหากคุณตั้งค่า outline: none
) แต่การมีรูปแบบโฟกัสที่กำหนดเองที่มองเห็นได้ชัดเจนกว่าจะช่วยปรับปรุงประสบการณ์ของผู้ใช้
รูปแบบโฟกัสเริ่มต้นของลิงก์ใน Chrome 103 จะมีหน้าตาดังนี้
![เส้นขอบสีน้ำเงินขนาด 2 พิกเซลรอบๆ ลิงก์ที่โฟกัสใน Chrome 103](https://web.dev/static/articles/website-navigation/image/a-blue-2px-outline-around-06dbe05f2f773.png?authuser=6&hl=th)
คุณสามารถปรับปรุงให้ดีขึ้นได้โดยระบุรูปแบบของคุณเองด้วยสีของคุณเอง การใช้ :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
![มองเห็นเส้นขอบสีเข้มขนาด 2 พิกเซลอย่างชัดเจนโดยมีระยะห่างด้านใน](https://web.dev/static/articles/website-navigation/image/clearly-visible-dark-2px-9fa411b864327.png?authuser=6&hl=th)
การไฮไลต์รายการเมื่อมีการโฟกัสทำได้หลายวิธี ขอแนะนำให้ใช้พร็อพเพอร์ตี้ outline
เนื่องจากจะไม่ทำให้เลย์เอาต์เสียหาย ซึ่งอาจเกิดขึ้นได้กับ border
และใช้ได้ดีกับโหมดคอนทราสต์สูงใน Windows คุณสมบัติที่ทำงานได้ไม่ดีคือ background-color
หรือ box-shadow
เนื่องจากอาจไม่แสดงเลยเมื่อใช้การตั้งค่าคอนทราสต์ที่กำหนดเอง
![เว็บไซต์ที่มีพื้นหลังสีเข้มซึ่งไฮไลต์เป็นสีม่วง](https://web.dev/static/articles/website-navigation/image/a-site-a-dark-background-4f9535f7666da.png?authuser=6&hl=th)
ยินดีด้วย คุณได้สร้างการนำทางหลักที่ได้รับการปรับปรุงอย่างต่อเนื่อง มีประโยชน์ในด้านความหมาย เข้าถึงได้ง่าย และเหมาะกับอุปกรณ์เคลื่อนที่
มีบางสิ่งที่ปรับปรุงได้เสมอ ตัวอย่างเช่น
- คุณอาจลองดักจับโฟกัสภายในการนำทาง หรือทำให้ส่วนที่เหลือของหน้าเป็นเฉินในวิวพอร์ตแคบๆ
- คุณสามารถเพิ่มลิงก์ข้ามที่ด้านบนสุดของหน้าเพื่อให้ผู้ใช้แป้นพิมพ์สามารถข้ามการนำทางได้
หากคุณจำได้ว่าบทความนี้เริ่มต้นได้อย่างไร โดยมีเป้าหมายที่ว่าโซลูชันนี้ควร "ไม่ง่ายเกินไปหรือซับซ้อนเกินไป" และนั่นคือจุดที่เรามาถึงแล้ว อย่างไรก็ตาม มีความเป็นไปได้ที่จะวางแผนการนำทางมากเกินไป
การนำทางกับเมนู
มีความแตกต่างที่ชัดเจนระหว่างการนำทางและเมนู การไปยังส่วนต่างๆ คือคอลเล็กชันของลิงก์สำหรับไปยังส่วนต่างๆ ของเอกสารที่เกี่ยวข้อง เมนูคือคอลเล็กชันของการทำงานที่จะกระทำในเอกสาร บางครั้งงานเหล่านี้อาจทับซ้อนกัน คุณอาจมีการนำทางที่มีปุ่มสำหรับดำเนินการบางอย่างด้วย เช่น การเปิดหน้าต่างโมดัล หรือคุณอาจมีเมนูที่มีการทำงานหนึ่งกำลังไปยังหน้าอื่น เช่น หน้าความช่วยเหลือ ในกรณีนี้ คุณไม่ควรรวมบทบาท ARIA เข้าด้วยกัน แต่ให้ระบุวัตถุประสงค์หลักของคอมโพเนนต์และเลือกมาร์กอัปและบทบาทตามความเหมาะสม
องค์ประกอบ <nav>
มีบทบาท ARIA โดยนัยของการนำทาง ซึ่งเพียงพอที่จะสื่อสารว่าองค์ประกอบนี้เป็นการนําทาง แต่บ่อยครั้งที่คุณเห็นว่าเว็บไซต์ใช้เมนู แถบเมนู และรายการเมนูด้วย เนื่องจากบางครั้งเราใช้คำเหล่านี้สลับกันไป การคิดว่าการใช้คำเหล่านี้ร่วมกันเพื่อปรับปรุงประสบการณ์การใช้งานของผู้ใช้โปรแกรมอ่านหน้าจออาจเหมาะสม ก่อนที่เราจะทราบว่าเหตุใดจึงเป็นเช่นนั้น มาดูคำนิยามอย่างเป็นทางการของบทบาทเหล่านี้กัน
บทบาทการนำทาง
คอลเล็กชันขององค์ประกอบการนำทาง (มักจะเป็นลิงก์) สำหรับการไปยังส่วนต่างๆ ในเอกสารหรือเอกสารที่เกี่ยวข้อง
การนำทาง (บทบาท) WAI-ARIA 1.1
บทบาทเมนู
เมนูมักเป็นรายการการทำงานหรือฟังก์ชันทั่วไปที่ผู้ใช้เรียกใช้ได้ บทบาทของเมนูจะเหมาะสมเมื่อรายการในเมนูแสดงในลักษณะที่คล้ายกับเมนูในแอปพลิเคชันเดสก์ท็อป
เมนู (บทบาท) WAI-ARIA 1.1
บทบาทแถบเมนู
การนำเสนอเมนูที่ยังคงมองเห็นได้และมักนำเสนอในแนวนอน บทบาทแถบเมนูจะใช้ในการสร้างแถบเมนูซึ่งคล้ายกับแถบที่พบในแอปพลิเคชันเดสก์ท็อป Windows, Mac และ Gnome แถบเมนูใช้เพื่อสร้างชุดคำสั่งที่ใช้บ่อยที่สอดคล้องกัน ผู้เขียนควรตรวจสอบว่าการโต้ตอบในแถบเมนูคล้ายคลึงกับการโต้ตอบบนแถบเมนูทั่วไปในอินเทอร์เฟซผู้ใช้แบบกราฟิกบนเดสก์ท็อป
แถบเมนู (บทบาท) WAI-ARIA 1.1
บทบาทเกี่ยวกับรายการในเมนู
ตัวเลือกในชุดตัวเลือกที่มีอยู่ในเมนูหรือแถบเมนู
menuitem (บทบาท) WAI-ARIA 1.1
ข้อกำหนดระบุชัดเจนมากในที่นี้ ใช้การนำทางสำหรับการนำทางในเอกสารหรือเอกสารที่เกี่ยวข้องและเมนูสำหรับรายการการกระทำหรือฟังก์ชันที่คล้ายกับเมนูในแอปพลิเคชันเดสก์ท็อปเท่านั้น หากคุณไม่ได้สร้าง Google เอกสารชุดถัดไป คุณอาจไม่จำเป็นต้องใช้บทบาทเมนูใดๆ สำหรับการนำทางหลัก
เวลาที่เหมาะสมสำหรับเมนู
การใช้งานหลักสำหรับรายการในเมนูไม่ใช่การนำทาง แต่มีไว้เพื่อดำเนินการต่างๆ สมมติว่าคุณมีรายการหรือตารางข้อมูล และผู้ใช้สามารถดำเนินการบางอย่างกับแต่ละรายการในลิสต์ได้ เพิ่มปุ่มในแต่ละแถวและแสดงการทำงานเมื่อผู้ใช้คลิกปุ่มดังกล่าว
<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 Authoring Practices (APG)
- Enter และ Space เพื่อเลือกรายการในเมนู
- ใช้ปุ่มลูกศรในทุกทิศทางเพื่อไปยังรายการต่างๆ
- แป้นหน้าแรกและสิ้นสุดเพื่อย้ายโฟกัสไปยังรายการแรกหรือรายการสุดท้ายตามลำดับ
- a-z เพื่อย้ายโฟกัสไปยังรายการเมนูถัดไปซึ่งมีป้ายกำกับที่ขึ้นต้นด้วยอักขระที่พิมพ์
- Esc เพื่อปิดเมนู
หากโปรแกรมอ่านหน้าจอตรวจพบเมนู ซอฟต์แวร์อาจเปลี่ยนโหมดการท่องเว็บโดยอัตโนมัติ ซึ่งทำให้ใช้แป้นพิมพ์ลัดที่กล่าวถึงก่อนหน้านี้ได้ ผู้ใช้โปรแกรมอ่านหน้าจอที่ไม่มีประสบการณ์อาจใช้เมนูดังกล่าวไม่ได้ เนื่องจากไม่รู้จักแป้นพิมพ์ลัดเหล่านี้หรือวิธีใช้
เช่นเดียวกับผู้ใช้แป้นพิมพ์ที่อาจคาดว่าจะใช้ Shift และ Shift + Tab ได้
มีหลายสิ่งหลายอย่างที่ต้องพิจารณาเมื่อคุณสร้างเมนูและแถบเมนู และพิจารณาว่าการใช้เมนูและแถบเมนูนั้นเหมาะสมหรือไม่ตั้งแต่แรก เมื่อคุณสร้างเว็บไซต์ทั่วไป เพียงต้องมีองค์ประกอบการนำทางพร้อมรายการและลิงก์เท่านั้น ซึ่งรวมถึงแอปพลิเคชันหน้าเว็บเดียว (SPA) หรือเว็บแอปด้วย สแต็กเบื้องหลังนั้นไม่สำคัญ หลีกเลี่ยงบทบาทในเมนู เว้นแต่ว่าคุณจะสร้างสิ่งที่อยู่ใกล้กับแอปพลิเคชันบนเดสก์ท็อปมาก
แหล่งข้อมูลเพิ่มเติม
- การแก้ไขรายการ โดย Scott O'hara
- อย่าใช้บทบาทเมนู ARIA สำหรับการไปยังส่วนต่างๆ ของไซต์ โดย Adrian Roselli
- เมนูและปุ่มเมนู โดย Heydon Pickering
- เมนู WAI-ARIA และสาเหตุที่คุณควรจัดการด้วยความระมัดระวังอย่างยิ่ง โดย Marco Zehe
- การซ่อนเนื้อหาอย่างมีความรับผิดชอบโดย Kitty Giraudel
- :Focus-visible Is Here โดย Matthias Ott
รูปภาพหลักโดย Mick Haupt