เช็กลิสต์เชิงเทคนิคสำหรับนักพัฒนา Front-end ครอบคลุมการเขียนโครงสร้าง HTML, การควบคุมการแสดงผลผ่าน CSS, การจัดการ WAI-ARIA และเกณฑ์ข้อบังคับใหม่ที่เพิ่มเข้ามาใน WCAG 2.2
โครงสร้าง Semantic HTML & Content Structure
- [ ] กำหนดภาษาของเอกสาร (3.1.1 Level A)
แท็ก<html lang="th">หรือlang="en"ต้องมีและระบุภาษาหลักอย่างถูกต้อง หากมีข้อความภาษาอื่นแทรก ให้ครอบด้วยแท็กที่มีlang="..."กำกับเฉพาะจุด - [ ] ลำดับหัวข้อตาม Hierarchy (1.3.1 Level A)
ใช้<h1>ถึง<h6>เรียงลำดับตามความสำคัญ ห้ามข้ามขั้น (เช่น จาก h2 กระโดดไป h4) และไม่ใช้แท็กหัวข้อเพียงเพื่อต้องการขยายขนาดตัวอักษร - [ ] ใช้ Landmark Elements ชัดเจน (1.3.1 Level A)
แบ่งสัดส่วนหน้าเว็บด้วย<header>,<nav>,<main>,<aside>,<footer>(หน้าเว็บต้องมี<main>เพียงหนึ่งเดียวต่อหน้า) - [ ] รูปภาพมี Alternative Text (1.1.1 Level A)
- รูปภาพสื่อความหมาย: ใส่
alt="คำอธิบายที่กระชับ" - รูปภาพตกแต่ง (Decorative): ใส่
alt=""หรือaria-hidden="true"เพื่อให้ Screen Reader ข้าม
- รูปภาพสื่อความหมาย: ใส่
- [ ] ฟอร์มและป้ายกำกับ (3.3.2 Level A, 1.3.1 Level A)
ทุก<input>,<select>,<textarea>ต้องเชื่อมโยงกับ<label for="id">โดยตรง (ห้ามใช้placeholderแทน<label>) - [ ] ใช้ Interactive Element ให้ถูกชนิด (4.1.2 Level A)
- ใช้
<button>สำหรับการสั่งการ (Action) หรือเปิด/ปิด Modal - ใช้
<a href="...">สำหรับการเปลี่ยนหน้าหรือปลายทาง URL - หลีกเลี่ยงการใช้
<div onClick>หรือ<span onClick>โดยไม่จำเป็น
- ใช้
รูปแบบการแสดงผลและสี (CSS Styling)
- [ ] ห้ามลบ Focus Outline ทิ้ง (2.4.7 Level AA)
ห้ามเขียนoutline: none;หรือoutline: 0;โดยไม่มีสไตล์ทดแทนเมื่อมีสถานะ:focus-visible - [ ] Focus Not Obscured (Minimum) (2.4.11 Level AA – ใหม่ใน 2.2)
เมื่อผู้ใช้เลื่อนคีย์บอร์ดไปยัง Element ใด ต้องไม่มี Sticky Header, Sticky Footer, หรือ Cookie Banner บดบัง Element นั้นจนมิด (ต้องมองเห็นส่วนหนึ่งของคอมโพเนนต์อย่างน้อยที่สุด) - [ ] อัตราส่วน Contrast ข้อความ (1.4.3 Level AA)
- ข้อความปกติ (ต่ำกว่า 18pt หรือต่ำกว่า 14pt ตัวหนา): คอนทราสต์ไม่น้อยกว่า 4.5:1
- ข้อความขนาดใหญ่ (ตั้งแต่ 18pt ขึ้นไป หรือ 14pt ตัวหนา): คอนทราสต์ไม่น้อยกว่า 3:1
- [ ] อัตราส่วน Contrast ของ UI Components (1.4.11 Level AA)
เส้นขอบของ Input, ไอคอนที่กดได้, และสถานะ Active ต้องมีคอนทราสต์กับพื้นหลังไม่น้อยกว่า 3:1 - [ ] Target Size (Minimum) (2.5.8 Level AA – ใหม่ใน 2.2)
จุดสัมผัสที่คลิกได้ (Pointer Targets) ต้องมีขนาดอย่างน้อย 24×24 CSS Pixels หรือหากคอมโพเนนต์เล็กกว่านั้น ต้องมี Spacing/Margin คั่นรอบด้านรวมกันไม่น้อยกว่า 24 พิกเซล เพื่อไม่ให้แตะโดนคอมโพเนนต์ข้างเคียง - [ ] รองรับการซูมและจัดเรียงใหม่ (1.4.10 Reflow Level AA)
หน้าเว็บต้องรองรับการซูม 400% ที่หน้าจอความกว้าง 1280px (เทียบเท่า viewport 320px) โดยไม่เกิดแถบเลื่อนแนวนอน (Horizontal Scroll) สองทิศทาง - [ ] ไม่สื่อสารด้วยสีเพียงอย่างเดียว (1.4.1 Level A)
การแจ้งเตือน Error หรือลิงก์ ต้องมีเส้นใต้, ไอคอน, หรือสัญลักษณ์ประกอบร่วมกับสีเสมอ
การควบคุมด้วยคีย์บอร์ดและการเคลื่อนไหว (Keyboard & Motion)
- [ ] เข้าถึงได้ด้วยคีย์บอร์ด 100% (2.1.1 Level A)
ใช้งานปุ่ม Tab, Shift+Tab, Enter, Space, และ Arrow Keys เข้าถึงและควบคุมทุกฟังก์ชันได้โดยไม่ต้องแตะเมาส์ - [ ] ไม่มีกับดักคีย์บอร์ด (2.1.2 No Keyboard Trap Level A)
เมื่อกด Tab เข้าไปในจุดใด (เช่น Modal Dialog) ต้องสามารถกด Tab ออกมาได้ หรือมีปุ่ม Esc เพื่อปิด Modal แล้วคืนโฟกัสกลับมาตำแหน่งเดิม - [ ] มี Skip Navigation Link (2.4.1 Level A)
มีลิงก์ซ่อนตัวอยู่บนสุดของหน้า<a href="#main-content" class="skip-link">ข้ามไปยังเนื้อหาหลัก</a>ที่จะแสดงขึ้นมาเมื่อกด Tab ครั้งแรก - [ ] ปิดหรือหยุด Motion ได้ (2.2.2 Level A, 2.3.3 Level AAA)
คอนเทนต์ที่มีการสไลด์อัตโนมัติ (Carousel), วิดีโอพื้นหลัง หรือ GIF เคลื่อนไหว ต้องมีปุ่ม Pause/Stop และรองรับ Media Query@media (prefers-reduced-motion: reduce) - [ ] Dragging Movements (2.5.7 Level AA – ใหม่ใน 2.2)
หากมีฟังก์ชันลากวาง (Drag and Drop) หรือเลื่อนแถบ Slider ต้องมีทางเลือกแบบคลิกครั้งเดียว (Single Pointer Alternative) เช่น มีปุ่มกดเลื่อนขึ้น/ลง หรือปุ่มกดเลือกแทนการลากเมาส์
การใช้งาน WAI-ARIA & Dynamic UI
กฎข้อแรกของ ARIA
“หากใช้ HTML พื้นฐานแก้ปัญหาได้ อย่าใช้ ARIA” (No ARIA is better than bad ARIA)
- [ ] ปุ่มที่มีแต่ไอคอน (4.1.2 Level A)
หากปุ่มใช้เฉพาะ SVG หรือ Icon Font ต้องใส่aria-label="ปิดหน้าต่าง"หรือซ่อนข้อความกำกับด้วยคลาส.sr-onlyเสมอ - [ ] แจ้งสถานะเปิด/ปิด (State Announcement)
- Dropdown หรือ Accordion: ใส่
aria-expanded="true/false"บนปุ่ม Trigger - Modal Dialog: ใส่
role="dialog"และaria-modal="true"พร้อมผูกaria-labelledby="dialog-title-id" - ปุ่มเปิด/ปิด (Toggle): ใส่
aria-pressed="true/false"
- Dropdown หรือ Accordion: ใส่
- [ ] แจ้งเตือนข้อมูลเปลี่ยนแปลงฉับพลัน (Live Regions 4.1.3 Level AA)
สำหรับข้อความแจ้ง Error หรือผลการโหลด ให้ใช้aria-live="polite"(หรือassertiveในกรณีฉุกเฉิน) เพื่อให้ Screen Reader อ่านข้อความใหม่โดยไม่ต้องโหลดหน้าเว็บใหม่ - [ ] Consistent Help (3.2.6 Level A – ใหม่ใน 2.2)
ข้อมูลช่วยเหลือ เช่น ลิงก์ติดต่อ เบอร์โทร หรือแชตบอต หากแสดงผลหลายหน้า ต้องวางอยู่ในลำดับสัมพัทธ์เดิมของหน้าเว็บเสมอ - [ ] Redundant Entry (3.3.7 Level A – ใหม่ใน 2.2)
เมื่อผู้ใช้กรอกข้อมูลในขั้นตอนแรก (เช่น ที่อยู่จัดส่ง) หน้าฟอร์มถัดไป (เช่น ที่อยู่ออกใบเสร็จ) ต้องมีตัวเลือกดึงข้อมูลเดิมมาแสดง หรือ Auto-populate โดยไม่ต้องให้ผู้ใช้พิมพ์ซ้ำ
สรุป Flow การ Audit ก่อน Deploy ขึ้น Production
- Automated Scan
รัน axe DevTools หรือ Lighthouse เพื่อเก็บ Low-hanging fruits (เช่น สีที่คอนทราสต์ตก หรือแท็ก img ที่ลืมใส่ alt) - Keyboard-only Navigation
ถอดมือออกจากเมาส์ แล้วลองกดปุ่ม Tab, Enter, Space, และลูกศร ทดสอบการกรอกฟอร์ม เปิด Modal และการกระโดดของโฟกัส - Screen Reader Testing
เปิด NVDA (บน Windows) หรือ VoiceOver (บน macOS/iOS) แล้วหลับตาฟังการใช้งาน ว่าระบบสื่อสารชื่อปุ่ม สถานะ และข้อผิดพลาดตรงกับที่ตาเห็นหรือไม่