ขอบเขต Shadow จะเปลี่ยนวิธีการทำงานของความหมายและ ARIA ความล้มเหลว 2 อย่างที่พบมากที่สุดคือความหมายที่ขาดหายไปภายใน Shadow Tree และการอ้างอิง ARIA ที่ใช้งานไม่ได้โดยไม่มีการแจ้งเตือนเนื่องจากไม่สามารถข้าม Shadow Root ได้
เริ่มต้นจากมาร์กอัปที่สื่อความหมาย: ใช้ <button>, <nav>, <ul> จริงภายในเทมเพลตเพื่อให้ความหมายส่วนใหญ่มาโดยอัตโนมัติ และสำรอง ElementInternals/ARIA ไว้สำหรับส่วนที่ขาดหายไป
ความหมายเริ่มต้นผ่าน ElementInternals ARIA mixin
ตั้งค่าบทบาทและสถานะ ARIA ขององค์ประกอบที่กำหนดเองใน JS ผ่าน ElementInternals แทนการเขียนแอตทริบิวต์ ARIA ลงในโฮสต์ วิธีนี้จะคงความหมายเป็นค่าเริ่มต้นที่คอมโพเนนต์เป็นเจ้าของ ขณะเดียวกันก็ยังคงอนุญาตให้ผู้บริโภคแทนที่ความหมายเหล่านั้นด้วยแอตทริบิวต์ใน Light DOM
class ToggleSwitch extends HTMLElement {
#internals;
constructor() {
super();
this.#internals = this.attachInternals();
this.#internals.role = 'switch'; // default role, no host attribute needed
this.#internals.ariaChecked = 'false'; // exposed to the accessibility tree
this.addEventListener('click', () => this.toggle());
this.addEventListener('keydown', (e) => {
if (e.key === ' ') { e.preventDefault(); this.toggle(); }
});
}
connectedCallback() {
// Put the host in the tab order on connect (setting tabIndex in the constructor throws on createElement).
if (!this.hasAttribute('tabindex')) this.tabIndex = 0;
}
toggle() {
const on = this.#internals.ariaChecked !== 'true';
this.#internals.ariaChecked = String(on);
}
}
customElements.define('toggle-switch', ToggleSwitch);
วิธีนี้จะช่วยหลีกเลี่ยงการสร้างความสับสนใน DOM ด้วยแอตทริบิวต์ ARIA และป้องกันไม่ให้ผู้ใช้ลบแอตทริบิวต์เหล่านั้นโดยไม่ตั้งใจ ขณะที่แผนผังการช่วยเหลือพิเศษยังคงเห็นบทบาทและสถานะที่ถูกต้อง
การจัดการโฟกัสและ delegatesFocus
- เมื่อองค์ประกอบโฮสต์เป็นตัวควบคุมแบบอินเทอร์แอกทีฟและมีบทบาทและสถานะผ่าน
ElementInternals(เช่นToggleSwitchด้านบน) ให้วางโฮสต์ในลำดับแท็บภายในconnectedCallback(if (!this.hasAttribute('tabindex')) this.tabIndex = 0— ห้ามวางในคอนสตรัคเตอร์ ซึ่งจะแสดงข้อผิดพลาดในdocument.createElement) เพื่อให้โฟกัสอยู่ที่โฮสต์และเทคโนโลยีความช่วยเหลือพิเศษจะประกาศบทบาทและสถานะของโฮสต์ อย่าตั้งค่าtabindexในโฮสต์สำหรับคอมโพเนนต์แบบคงที่และไม่โต้ตอบ (เช่น ข้อความไฮไลต์หรือการ์ด) - แนบ Shadow Root ด้วย
delegatesFocus: trueเมื่อคอมโพเนนต์รวมการควบคุมที่โฟกัสได้ภายในซึ่งเป็นเจ้าของความหมาย (หรือในองค์ประกอบที่กำหนดเองที่เชื่อมโยงกับแบบฟอร์มด้วยstatic formAssociated = true) การโฟกัสโฮสต์ (และการคลิก<label>ที่เชื่อมโยงสำหรับองค์ประกอบที่เชื่อมโยงกับแบบฟอร์ม) จะส่งต่อโฟกัสไปยังองค์ประกอบย่อยที่โฟกัสได้รายการแรก และ:focusจะตรงกับโฮสต์ อย่ารวมdelegatesFocus: trueกับบทบาท/สถานะในโฮสต์ ไม่เช่นนั้นโฟกัสจะไปอยู่ที่องค์ประกอบด้านในและข้ามสถานะของโฮสต์ไป - สำหรับการย้ายโฟกัสหรือการย้ายโฟกัสไปยังส่วนที่เพิ่งแสดง ให้กำหนด
tabindex="-1"ให้กับเป้าหมายและเรียกใช้.focus()โดยกำหนดเป้าหมายที่โฟกัสได้โดยใช้โปรแกรมอย่างชัดเจนแทนที่จะอาศัยลำดับแท็บ
ความสัมพันธ์ของ ARIA ใน Shadow Root
- บังคับ:
idที่อ้างอิงโดยaria-labelledby,aria-describedby,aria-controlsฯลฯ จะแก้ไขได้ภายในโครงสร้างของตัวเองขององค์ประกอบที่อ้างอิงเท่านั้น แอตทริบิวต์ที่อิงตามidใน Light DOM ไม่สามารถชี้ไปยังidภายใน Shadow Tree และในทางกลับกัน ระบบจะไม่สนใจการอ้างอิงโดยไม่มีการแจ้งเตือน - หากต้องการข้ามขอบเขต ให้ใช้พร็อพเพอร์ตี้ element ของ ARIA ที่แสดง (เช่น
ariaLabelledByElements,ariaDescribedByElementsเป็นต้น) ซึ่งใช้การอ้างอิงองค์ประกอบ JS โดยตรงแทนรหัส โดยจะแก้ไขภายนอก: องค์ประกอบภายใน Shadow Tree สามารถชี้ไปยังเป้าหมายใน Light DOM หรือโครงสร้างระดับบนสุด (รวมถึงเนื้อหาที่แบ่งช่อง) เพื่อให้คุณติดป้ายกำกับการควบคุมภายใน Shadow จากเนื้อหา Light DOM ได้ ซึ่งเป็นสิ่งที่การอ้างอิงidไม่สามารถแสดงได้ - แต่จะไม่แก้ไขเข้าด้านใน: องค์ประกอบจะอ้างอิงเข้าไปใน Shadow Tree ที่สืบทอดมาไม่ได้ (เช่น โฮสต์จะติดป้ายกำกับโดยเนื้อหา Shadow ของตัวเองไม่ได้) สำหรับทิศทางนั้น กลไก Reference Target ที่เกิดขึ้นใหม่เป็นทิศทางมาตรฐาน แต่ยังไม่มีให้บริการในวงกว้าง
- เมื่อไม่สามารถแสดงความสัมพันธ์ได้ไม่ว่าด้วยวิธีใดก็ตาม ให้เก็บความสัมพันธ์นั้นไว้ภายในต้นไม้เดียว (แสดงผลป้ายกำกับในต้นไม้เดียวกัน) หรือใช้ข้อความ
aria-labelแทนการอ้างอิงid
กลยุทธ์สำรอง
ในกรณีที่ไม่มีมิกซ์อิน ElementInternals ARIA ให้ตั้งค่าบทบาทและสถานะ ARIA เป็นแอตทริบิวต์ในโฮสต์แทน (this.setAttribute('role', 'switch')) ซึ่งจะใช้ได้ทุกที่ โดยแลกกับการใส่แอตทริบิวต์ใน DOM ที่ผู้บริโภคสามารถลบล้างได้
ในกรณีที่พร็อพเพอร์ตี้องค์ประกอบ ARIA ที่แสดงผลไม่พร้อมใช้งาน ให้ใช้แอตทริบิวต์ aria-* ที่อิงตาม id สำหรับความสัมพันธ์ในโครงสร้างเดียวกัน ป้ายกำกับข้ามขอบเขตไม่มีรายการที่เทียบเท่าซึ่งอิงตาม id ดังนั้นให้กลับไปใช้ข้อความ aria-label