จดจ่อ

องค์ประกอบอินเทอร์แอกทีฟ ซึ่งรวมถึงตัวควบคุมแบบฟอร์ม ลิงก์ และปุ่มต่างๆ จะโฟกัสได้และ Tab ตามค่าเริ่มต้น องค์ประกอบที่แตะได้เป็นส่วนหนึ่งของลำดับการโฟกัสตามลำดับของเอกสาร องค์ประกอบอื่นๆ ไม่มีปฏิกิริยาโต้ตอบ กล่าวคือไม่มีการโต้ตอบ แอตทริบิวต์ HTML จะช่วยให้องค์ประกอบแบบอินเทอร์แอกทีฟมีปฏิกิริยาโต้ตอบ และทำให้องค์ประกอบแบบเฉื่อยเป็นแบบอินเทอร์แอกทีฟได้

โดยค่าเริ่มต้น ลำดับการโฟกัสการนำทางจะเหมือนกับลำดับภาพ ซึ่งเป็นลำดับซอร์สโค้ด มีแอตทริบิวต์ HTML ที่เปลี่ยนลำดับนี้และพร็อพเพอร์ตี้ CSS ได้ การเปลี่ยนลำดับแท็บโดยใช้ HTML หรือลำดับการแสดงผลภาพด้วย CSS อาจส่งผลเสียต่อประสบการณ์ของผู้ใช้

อย่าเปลี่ยนลำดับของแท็บที่รับรู้ได้และแท็บจริงด้วย CSS และ HTML จาก 2 ตัวอย่างต่อไปนี้แสดงให้เห็น ลำดับแท็บที่แตกต่างจากลำดับที่คาดไว้จะทำให้ผู้ใช้สับสนและแย่ต่อประสบการณ์ของผู้ใช้

ในตัวอย่างนี้ ค่าของแอตทริบิวต์ tabindex ทำให้ลำดับแท็บสับสน ดังนี้

ในตัวอย่างนี้ CSS ทำให้เกิดความแตกต่างระหว่างลำดับของแท็บและลำดับภาพของเนื้อหา

การประกาศ flex-flow: row-reverse; กลับลำดับภาพแล้ว นอกจากนี้ ระบบยังนำคุณสมบัติ order ของ CSS ไปใช้กับคำที่ 6 ซึ่งก็คือ "This" ซึ่งจะย้ายการมองเห็นภาพ 1 คำนั้น ลำดับการกดแท็บคือลําดับของโค้ด ซึ่งไม่ตรงกับลำดับการเห็นอีกต่อไป ส่งผลให้ผู้ใช้แป้นพิมพ์ตัดการเชื่อมต่อ

การทำให้องค์ประกอบเฉื่อยเป็นแบบอินเทอร์แอกทีฟ

คุณเพิ่มแอตทริบิวต์ contenteditable และ tabindex ซึ่งเป็นแอตทริบิวต์ส่วนกลางลงในองค์ประกอบใดก็ได้ ซึ่งทำให้โฟกัสในกระบวนการได้ นอกจากนี้ องค์ประกอบที่โฟกัสได้ยังโฟกัสได้ด้วยเมาส์หรือตัวชี้โดยตั้งค่าแอตทริบิวต์ autofocus หรือตามสคริปต์ เช่น ด้วย element.focus()

แอตทริบิวต์ tabindex

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

แอตทริบิวต์ tabindex จะใช้ค่าเป็นจำนวนเต็ม ค่าลบจะทำให้องค์ประกอบโฟกัสได้ แต่กด Tab ไม่ได้ ค่า tabindex ของ 0 ทำให้องค์ประกอบที่โฟกัสได้และ Tab ได้เป็นการเพิ่มองค์ประกอบที่จะใช้กับลำดับการนำทางโฟกัสตามลำดับของซอร์สโค้ด ค่า 1 ขึ้นไปจะทำให้องค์ประกอบที่โฟกัสได้และ Tab ได้ แต่จะเพิ่มเข้าไปในลำดับการกด Tab ที่จัดลำดับความสำคัญและควรหลีกเลี่ยงอย่างที่เราเห็นด้านบน

ในหน้านี้ ปุ่มแชร์ <share-action> เป็นองค์ประกอบที่กำหนดเอง tabindex="0" จะเพิ่มองค์ประกอบที่โฟกัสได้ไม่ปกตินี้ลงในลำดับการกด Tab เริ่มต้นของแป้นพิมพ์

<share-action authors="@front-end.social/@estellevw" data-action="click" data-category="web.dev" data-icon="share" data-label="share, mastodon" role="button" tabindex="0">
  <svg aria-label="share" role="img" xmlns="http://www.w3.org/2000/svg">
    <use href="#shareIcon" />
  </svg>
  <span>Share</span>
</share-action>

มีองค์ประกอบที่กำหนดเองอีก 1 รายการในหน้านี้ คือ การนำทางในเครื่อง มีองค์ประกอบที่กำหนดเองซึ่งมีค่า tabindex เป็นลบ ดังนี้

<web-navigation-drawer type="standard" tabindex="-1">

แอตทริบิวต์ tabindex ที่มีค่าลบจะทำให้โฟกัสองค์ประกอบได้ แต่กด Tab ไม่ได้ องค์ประกอบรับโฟกัสได้ เช่น ผ่าน HTMLElement.focus() แต่ไม่ได้เป็นส่วนหนึ่งของลำดับการโฟกัสตามลำดับที่โฟกัส รูปแบบสำหรับองค์ประกอบที่โฟกัสและแท็บไม่ได้คือการใช้ tabindex="-1" โปรดทราบว่าหากคุณเพิ่ม tabindex="-1" ลงในองค์ประกอบแบบอินเทอร์แอกทีฟ องค์ประกอบดังกล่าวจะแท็บไม่ได้อีกต่อไป

เมธอด element.focus() ใช้เพื่อตั้งค่าโฟกัสไปยังองค์ประกอบที่โฟกัสได้ โปรดทราบว่าเบราว์เซอร์จะเลื่อนองค์ประกอบที่โฟกัสไว้เข้ามาในมุมมอง ด้วยเหตุนี้ คุณจึงควรหลีกเลี่ยงการใช้ element.focus({preventScroll:true}) เนื่องจากการเน้นไปที่องค์ประกอบที่มองไม่เห็นจะทำให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ไม่ดี

หากต้องการค้นหาเอกสารเพื่อดูว่าองค์ประกอบใดโฟกัสอยู่ ให้ใช้พร็อพเพอร์ตี้ Document.activeElement แบบอ่านอย่างเดียว

องค์ประกอบที่มี tabindex เท่ากับ 1 ขึ้นไปจะรวมอยู่ในลําดับแท็บที่แยกต่างหาก คุณจะสังเกตเห็นได้ใน Codepen แท็บจะเริ่มในลำดับแยกต่างหาก โดยเรียงจากค่าต่ำสุดไปค่าสูงสุด ก่อนจะผ่านในลำดับปกติ (ไม่ได้ตั้งค่า tabindex หรือ tabindex="0") ตามลำดับซอร์ส

tabindex ที่มีค่าบวกจะทำให้องค์ประกอบอยู่ในลําดับการโฟกัสที่สําคัญ ซึ่งอาจทําให้ลำดับโฟกัสวุ่นวายได้ หลีกเลี่ยงการแก้ไขลำดับ DOM ด้วย tabindex คำสั่ง Tab ที่มีการแก้ไขสามารถสร้างประสบการณ์ที่ไม่ดีแก่ผู้ใช้ แต่นักพัฒนาซอฟต์แวร์ยังจัดการและดูแลรักษาได้ยาก

แอตทริบิวต์ contenteditable

มีการกล่าวถึงแอตทริบิวต์ contenteditable ก่อนหน้านี้ การตั้งค่า contenteditable="true" ในองค์ประกอบใดก็ตามจะทำให้องค์ประกอบนั้นแก้ไขได้ โฟกัสได้ และเป็นส่วนหนึ่งของลำดับแท็บ ลักษณะการโฟกัสคล้ายกับการตั้งค่า tabindex="0" แต่ไม่เหมือนกัน องค์ประกอบ contenteditable ที่ซ้อนกันจะโฟกัสได้ แต่กด Tab ไม่ได้ หากต้องการทำให้องค์ประกอบ contenteditable ที่ฝังเป็นแบบ Tab เข้าถึงได้ ให้เพิ่ม tabindex="0" ซึ่งจะเพิ่มไปยังลำดับการนำทางที่โฟกัสตามลำดับ

ให้ความสำคัญกับองค์ประกอบแบบอินเทอร์แอกทีฟ

แอตทริบิวต์ autofocus

แม้ว่าบูลีน autofocus คือแอตทริบิวต์ส่วนกลาง ซึ่งตั้งค่าในองค์ประกอบใดก็ได้ แต่จะไม่ทำให้องค์ประกอบแบบอินเทอร์แอ็กทีฟ เมื่อโหลดหน้าเว็บ องค์ประกอบที่โฟกัสได้รายการแรกที่มีชุดแอตทริบิวต์ autofocus จะได้รับการโฟกัส ตราบใดที่องค์ประกอบนั้นแสดงอยู่และไม่ได้ฝังอยู่ใน <dialog>

การตั้งค่าการโฟกัสที่เนื้อหาโดยอัตโนมัติอาจทำให้สับสนได้ การตั้งค่า autofocus ในตัวควบคุมแบบฟอร์มหมายความว่าตัวควบคุมแบบฟอร์มจะเลื่อนเข้ามาในมุมมองเมื่อโหลดหน้าเว็บ ผู้ใช้ทุกคน ซึ่งรวมถึงผู้ใช้โปรแกรมอ่านหน้าจอและผู้ใช้ที่มีวิวพอร์ตขนาดเล็ก อาจไม่ "เห็น" วิธีการสำหรับแบบฟอร์ม โดยอาจเลื่อนผ่านป้ายกำกับที่ปรากฏตามปกติของตัวควบคุมแบบฟอร์ม แอตทริบิวต์ autofocus จะไม่เปลี่ยนลำดับการโฟกัสตามลำดับของเอกสาร ระบบจะข้ามองค์ประกอบในลำดับที่อยู่ก่อน ระบบจะข้ามองค์ประกอบโฟกัสอัตโนมัติ ด้วยเหตุนี้ จึงไม่แนะนําให้ระบุแอตทริบิวต์ autofocus

ข้อยกเว้นสำหรับคำแนะนำ "อย่าใช้ autofocus" คือการรวมแอตทริบิวต์ autofocus ภายในองค์ประกอบ <dialog> เมื่อเปิดกล่องโต้ตอบ เบราว์เซอร์จะโฟกัสที่องค์ประกอบอินเทอร์แอกทีฟที่โฟกัสได้รายการแรกภายใน <dialog> โดยอัตโนมัติ ซึ่งหมายความว่าไม่จำเป็นต้องใช้ autofocus กับองค์ประกอบ หากต้องการให้องค์ประกอบแบบอินเทอร์แอกทีฟที่เฉพาะเจาะจงภายในกล่องโต้ตอบได้รับโฟกัสเมื่อกล่องโต้ตอบเปิดขึ้น ให้เพิ่มแอตทริบิวต์ autofocus ลงในองค์ประกอบนั้น

<dialog open>
  <form method="dialog">
    <button type="submit" autofocus>close</button>
  </form>
</dialog>

แอตทริบิวต์ autofocus ที่ตั้งค่าไว้ในการปิด <button> ช่วยให้มั่นใจได้ว่าจะได้รับโฟกัสเมื่อกล่องโต้ตอบเปิดอยู่ เนื่องจากเป็นองค์ประกอบแรก ในกล่องโต้ตอบ องค์ประกอบนี้จะได้รับการโฟกัสไม่ว่าในกรณีใดก็ตาม โดยค่าเริ่มต้น เมื่อมีการเปิดกล่องโต้ตอบ องค์ประกอบที่โฟกัสได้รายการแรกภายในกล่องโต้ตอบจะได้รับการโฟกัส เว้นแต่องค์ประกอบอื่นภายในกล่องโต้ตอบจะมีการตั้งค่าแอตทริบิวต์ autofocus ไว้

การทำให้องค์ประกอบแบบอินเทอร์แอกทีฟมีปฏิกิริยาโต้ตอบ

นอกจากนี้ ยังมีแอตทริบิวต์ HTML ที่สามารถนำองค์ประกอบแบบอินเทอร์แอกทีฟออกจากลำดับการกด Tab ได้ การรวม tabindex เชิงลบลงในองค์ประกอบที่โฟกัสได้ การเพิ่มแอตทริบิวต์ disabled ไปยังตัวควบคุมแบบฟอร์มที่รองรับ และการเพิ่มแอตทริบิวต์ inert ส่วนกลางลงในคอนเทนเนอร์จะทำให้องค์ประกอบทั้งหมดสลับไม่ได้ แอตทริบิวต์ 3 รายการนี้ใช้แทนกันไม่ได้

ค่า tabindex เชิงลบ

ตามที่เราได้เรียนรู้ข้างต้น แอตทริบิวต์ tabindex ที่มีค่าลบจะทำให้องค์ประกอบโฟกัสได้ แต่กด Tab ไม่ได้ แม้ว่าการเพิ่ม tabindex="0" ลงในองค์ประกอบที่โฟกัสได้โดยค่าเริ่มต้น ซึ่งรวมถึงลิงก์ ปุ่ม ตัวควบคุมแบบฟอร์ม และองค์ประกอบที่ contenteditable เป็นการดำเนินการที่ไม่จำเป็น ซึ่งรวมถึง tabindex ที่มีค่าลบจะนำองค์ประกอบที่กด Tab ตามปกติออกจากลำดับการโฟกัสตามลำดับ

ค่า tabindex เชิงลบจะป้องกันไม่ให้ผู้ใช้แป้นพิมพ์โฟกัสที่องค์ประกอบแบบอินเทอร์แอกทีฟ แต่ไม่ได้ปิดใช้องค์ประกอบนั้น ผู้ใช้เคอร์เซอร์จะยังคงโฟกัสที่องค์ประกอบได้ หากต้องการปิดใช้องค์ประกอบ ให้ใช้แอตทริบิวต์ disabled

ปิดใช้

แอตทริบิวต์บูลีน Disabled ทำให้ฟอร์มควบคุมสิ่งที่จะใช้และองค์ประกอบสืบทอด (หากมี) ที่ไม่สามารถโฟกัสได้ ตัวควบคุมแบบฟอร์มที่ปิดใช้แล้วจะไม่สามารถโฟกัสได้ ไม่มีกิจกรรมการคลิก และจะไม่ส่งเมื่อส่งแบบฟอร์ม โปรดทราบว่า disabled ไม่ใช่แอตทริบิวต์ร่วม การตั้งค่านี้จะมีผลกับ <button>, <input>, <optgroup>, <option>, <select>, <textarea>, องค์ประกอบที่กำหนดเองที่เกี่ยวข้องกับแบบฟอร์ม และ <fieldset> เมื่อตั้งค่าเป็น <optgroup> หรือ <fieldset> ระบบจะปิดใช้การควบคุมแบบฟอร์มย่อยทั้งหมด ยกเว้นเนื้อหาของ <legend> แรกของ <fieldset>

องค์ประกอบเดียวกันที่รองรับ disabled ก็กำหนดเป้าหมายได้ด้วย Pseudoclass ของ :disabled และ :enabled เช่นกัน โดยทั่วไปองค์ประกอบที่ปิดใช้ด้วยแอตทริบิวต์ disabled จะมีสไตล์เป็นสีเทาอ่อนผ่านสไตล์ชีตของ User Agent แม้ว่าจะตั้งค่า accent-color ไว้ก็ตาม

เมื่อมีแอตทริบิวต์บูลีน การแสดงแอตทริบิวต์จะปิดใช้องค์ประกอบที่เปิดใช้องค์ประกอบอื่น คุณจะตั้งค่าเป็น false ไม่ได้ หากต้องการเปิดใช้องค์ประกอบที่ปิดใช้อีกครั้ง คุณต้องนำแอตทริบิวต์ออก โดยทั่วไปจะต้องทำผ่าน Element.removeAttribute('disabled')

พร็อพเพอร์ตี้ HTMLInputElement.disabled ช่วยให้คุณตรวจสอบว่าอินพุตปิดใช้อยู่หรือไม่ เนื่องจาก disabled ไม่ใช่แอตทริบิวต์ส่วนกลาง จึงไม่รับค่ามาจาก HTMLElement แต่อินเทอร์เฟซองค์ประกอบที่รองรับทุกรายการ เช่น HTMLSelectElement, HTMLTextareaElement มีพร็อพเพอร์ตี้แบบอ่านอย่างเดียวที่เหมือนกัน

แอตทริบิวต์ disabled ใช้ไม่ได้กับองค์ประกอบ inert ปกติที่กำหนดให้โฟกัสผ่าน tabindex หรือ contenteditable ได้ นอกจากนี้ยังไม่มีผลกับองค์ประกอบ <form> เองด้วย หากต้องการปิดใช้ฟีเจอร์เหล่านี้ ให้ใช้แอตทริบิวต์ inert ส่วนกลาง

แอตทริบิวต์ inert

เมื่อเพิ่มแอตทริบิวต์บูลีนร่วม inert ลงในองค์ประกอบ องค์ประกอบนั้นและเนื้อหาที่ซ้อนกันทั้งหมดจะถูกปิดใช้งาน (คลิกหรือแตะไม่ได้) และนำออกจากแผนผังการช่วยเหลือพิเศษ แม้ว่า inert จะใช้กับองค์ประกอบใดก็ได้ แต่โดยทั่วไปแล้วจะใช้สำหรับส่วนต่างๆ ของเนื้อหา เช่น เนื้อหาที่นอกหน้าจอหรือเนื้อหาที่ซ่อนไว้

เมื่อใช้ disabled กับตัวควบคุมแบบฟอร์ม เบราว์เซอร์จะมีการจัดรูปแบบเริ่มต้นและสามารถจัดรูปแบบโดยใช้คลาสเทียม :disabled แอตทริบิวต์ inert ไม่มีตัวบ่งชี้แบบภาพและไม่มี Pseudoclass ที่ตรงกัน (แต่ตัวเลือกแอตทริบิวต์ของ [inert] ตรงกัน)

การใช้ inert ในเนื้อหาที่มองเห็นได้โดยไม่มีรูปแบบที่บ่งบอกถึงความเฉื่อยอาจทำให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ไม่ดี เนื่องจากเนื้อหาที่ไม่มีความเฉื่อยไม่มีให้ใช้งานสำหรับผู้ใช้โปรแกรมอ่านหน้าจอ อาจทำให้เกิดความสับสนเมื่อผู้ใช้โปรแกรมอ่านหน้าจอเห็นเนื้อหาบนหน้าจอที่ไม่สามารถเข้าถึงในเครื่องมือช่วยเหลือพิเศษได้ ทำให้เห็นความเฉื่อยชัดๆ ได้ผ่านทาง CSS

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

ทดสอบความเข้าใจ

ทดสอบความเข้าใจ

ทดสอบความรู้ในการโฟกัส

หากไม่สามารถโฟกัสองค์ประกอบใด องค์ประกอบนั้นเรียกว่าอะไร

ล้าง
โปรดลองอีกครั้ง
ความเฉื่อย
ถูกต้องแล้ว!
ซ่อนอยู่
โปรดลองอีกครั้ง

จะเกิดอะไรขึ้นหากองค์ประกอบมีแอตทริบิวต์ disabled

กล้องจะโฟกัสไม่ได้
ถูกต้องแล้ว!
ซึ่งจะไม่แสดง
โปรดลองอีกครั้ง
หากเป็นองค์ประกอบแบบฟอร์ม ระบบจะไม่ส่งข้อมูลดังกล่าว
ถูกต้องแล้ว!