PlusMagi's Blog By Pitt Phunsanit Technology Front-end Developer Checklist: ตรวจสอบ WCAG 2.2 (Level AA)

Front-end Developer Checklist: ตรวจสอบ WCAG 2.2 (Level AA)

เช็กลิสต์เชิงเทคนิคสำหรับนักพัฒนา 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"
  • [ ] แจ้งเตือนข้อมูลเปลี่ยนแปลงฉับพลัน (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

  1. Automated Scan
    รัน axe DevTools หรือ Lighthouse เพื่อเก็บ Low-hanging fruits (เช่น สีที่คอนทราสต์ตก หรือแท็ก img ที่ลืมใส่ alt)
  2. Keyboard-only Navigation
    ถอดมือออกจากเมาส์ แล้วลองกดปุ่ม Tab, Enter, Space, และลูกศร ทดสอบการกรอกฟอร์ม เปิด Modal และการกระโดดของโฟกัส
  3. Screen Reader Testing
    เปิด NVDA (บน Windows) หรือ VoiceOver (บน macOS/iOS) แล้วหลับตาฟังการใช้งาน ว่าระบบสื่อสารชื่อปุ่ม สถานะ และข้อผิดพลาดตรงกับที่ตาเห็นหรือไม่

Exit mobile version