0Pricing
React Academy · บทเรียน

การจัดการโฟกัสและกับดักแป้นพิมพ์ในโมดัล

คงโฟกัสไว้ภายในโมดัลที่เปิดอยู่เพื่อการเข้าถึงที่ดี โดยใช้ useRef และตัวฟังอีเวนต์

การจัดการโฟกัสและกับดักแป้นพิมพ์ในโมดัล เป็นบทเรียน React Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน

ยินดีต้อนรับ

ในบทเรียนนี้ คุณจะนำกับดัก focus มาใช้ภายในโมดัล เพื่อไม่ให้ผู้ใช้แป้นพิมพ์กด Tab ออกจากโมดัลที่เปิดอยู่ได้ ซึ่งเป็นข้อกำหนดสำคัญด้านการเข้าถึง (WCAG 2.4.3)

เหตุผลที่ต้องมีกับดัก Focus

เมื่อโมดัลเปิดอยู่ ผู้ใช้แป้นพิมพ์ควรโต้ตอบได้เฉพาะกับเนื้อหาของโมดัลเท่านั้น หากไม่มีกับดัก focus การกด Tab จะย้าย focus ไปยังองค์ประกอบด้านหลังชั้นซ้อนโมดัล องค์ประกอบเหล่านั้นถูกซ่อนด้วยสายตาแต่ยังเข้าถึงได้

กับดัก Focus คืออะไร

กับดัก focus จะดักจับเหตุการณ์ปุ่ม Tab และ Shift+Tab และเมื่อ focus กำลังจะออกจากโมดัล จะวน focus กลับไปยังองค์ประกอบ focusable แรกหรือสุดท้ายภายในโมดัล

การค้นหาองค์ประกอบ Focusable

ใช้ querySelectorAll พร้อมตัวเลือกที่ครอบคลุมองค์ประกอบแบบโต้ตอบทั้งหมด แล้วกรององค์ประกอบที่ปิดใช้งานหรือซ่อนอยู่ออก
const FOCUSABLE = [
  'a[href]', 'button:not([disabled])',
  'input:not([disabled])', 'select', 'textarea',
  '[tabindex]:not([tabindex="-1"])'
].join(',');

const focusable = Array.from(
  modalRef.current.querySelectorAll(FOCUSABLE)
);

การนำกับดักไปใช้

รับฟังเหตุการณ์ keydown บนคอนเทนเนอร์โมดัล เมื่อกด Tab หาก focus อยู่ที่องค์ประกอบสุดท้าย ให้ย้ายไปยังองค์ประกอบแรก เมื่อกด Shift+Tab หาก focus อยู่ที่องค์ประกอบแรก ให้ย้ายไปยังองค์ประกอบสุดท้าย
function handleTab(e) {
  const focusable = /* array of focusable elements */;
  const first = focusable[0];
  const last = focusable[focusable.length - 1];
  if (e.key !== 'Tab') return;
  if (e.shiftKey) {
    if (document.activeElement === first) {
      e.preventDefault(); last.focus();
    }
  } else {
    if (document.activeElement === last) {
      e.preventDefault(); first.focus();
    }
  }
}

การย้าย Focus เมื่อเปิด

เมื่อโมดัลเปิด ให้ย้าย focus ไปยังองค์ประกอบ focusable แรกภายในโมดัล หรือไปยังคอนเทนเนอร์โมดัลเองด้วย `tabIndex=-1` วิธีนี้ป้องกันไม่ให้ focus ยังคงอยู่ที่ปุ่มซึ่งเปิดโมดัล
useEffect(() => {
  if (isOpen) {
    const first = modalRef.current?.querySelector(FOCUSABLE);
    first?.focus();
  }
}, [isOpen]);

การคืน Focus เมื่อปิด

เมื่อโมดัลปิด ให้คืน focus ไปยังองค์ประกอบที่ active ก่อนโมดัลเปิด เก็บ ref ของ `document.activeElement` ไว้ในขณะที่โมดัลเปิด
const previousFocus = useRef(null);

useEffect(() => {
  if (isOpen) {
    previousFocus.current = document.activeElement;
  } else {
    previousFocus.current?.focus();
  }
}, [isOpen]);

การใช้ไลบรารี focus-trap-react

สำหรับการใช้งานจริง ควรพิจารณาไลบรารี **focus-trap-react** ไลบรารีนี้จัดการกรณีขอบทั้งหมด ได้แก่ shadow DOM, iframe, องค์ประกอบ focusable ที่เพิ่มแบบไดนามิก และการปิดใช้งานเมื่อกด Escape
import FocusTrap from 'focus-trap-react';

{isOpen && (
  <FocusTrap>
    <div role="dialog" aria-modal="true">
      {children}
    </div>
  </FocusTrap>
)}

แอตทริบิวต์ ARIA สำหรับโมดัล

เพิ่ม `role="dialog"` และ `aria-modal="true"` ให้กับคอนเทนเนอร์โมดัล เพิ่ม `aria-labelledby` ที่ชี้ไปยังหัวข้อของโมดัล วิธีนี้บอกโปรแกรมอ่านหน้าจอว่ากล่องโต้ตอบเป็นโมดัลและประกาศข้อมูลได้อย่างถูกต้อง
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
>
  <h2 id="modal-title">Confirm Delete</h2>
  ...
</div>

แอตทริบิวต์ Inert สำหรับพื้นหลัง

แอตทริบิวต์ `inert` ของ HTML บนคอนเทนเนอร์จะนำองค์ประกอบทั้งหมดออกจากลำดับ focus และการเข้าถึงของโปรแกรมอ่านหน้าจอ กำหนด `document.getElementById('root').inert = true` ขณะที่โมดัลเปิดอยู่ เพื่อบล็อกพื้นหลังอย่างรัดกุม
useEffect(() => {
  const root = document.getElementById('root');
  if (isOpen) root.setAttribute('inert', '');
  else root.removeAttribute('inert');
}, [isOpen]);

ตรวจสอบอย่างรวดเร็ว

เมื่อผู้ใช้แป้นพิมพ์กด Tab ที่องค์ประกอบ focusable สุดท้ายภายในโมดัลที่มีกับดัก focus ควรเกิดอะไรขึ้น

สรุปทบทวน

คุณนำกับดัก focus มาใช้แล้ว: ค้นหาองค์ประกอบ focusable ดักจับ Tab/Shift+Tab ย้าย focus เมื่อเปิด และคืน focus เมื่อปิด สำหรับการใช้งานจริงให้ใช้ focus-trap-react และเพิ่ม role='dialog' กับ aria-modal สำหรับโปรแกรมอ่านหน้าจอ

บทถัดไป

บทเรียนถัดไป: **คำแนะนำเครื่องมือและเมนูดรอปดาวน์ด้วยพอร์ทัล** — คุณจะเรนเดอร์คำแนะนำเครื่องมือและเมนูดรอปดาวน์ที่หลุดออกจากคอนเทนเนอร์ overflow-hidden โดยใช้ createPortal

คำถามที่พบบ่อย

บทเรียน “การจัดการโฟกัสและกับดักแป้นพิมพ์ในโมดัล” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การจัดการโฟกัสและกับดักแป้นพิมพ์ในโมดัล” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การจัดการโฟกัสและกับดักแป้นพิมพ์ในโมดัล”

คงโฟกัสไว้ภายในโมดัลที่เปิดอยู่เพื่อการเข้าถึงที่ดี โดยใช้ useRef และตัวฟังอีเวนต์ คุณปฏิบัติ React Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การจัดการโฟกัสและกับดักแป้นพิมพ์ในโมดัล” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน React Academy นี้ได้ไหม

ได้ บทเรียน React Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. React Portals คืออะไร
  2. การสร้างคอมโพเนนต์โมดัลด้วย Portals
  3. การจัดการโฟกัสและกับดักแป้นพิมพ์ในโมดัล
  4. คำแนะนำเครื่องมือและเมนูดรอปดาวน์ด้วย Portals
← กลับไปที่ React Academy