ข้ามไปยังเนื้อหา

Host Element และ Shadow Boundary

CSS selector :host กำหนดเป้าหมายไปที่ host element — element ที่เป็นเจ้าของ shadow root — จากภายใน shadow CSS นี่เป็นวิธีเดียวที่จะสไตล์ box model ของ host element เอง (display, border, padding) จาก shadow CSS ของ component

:host {
display: inline-block;
border: 2px solid #6366f1;
}

:host(selector) ใช้สไตล์เฉพาะเมื่อ host element ตรงกับ selector ที่ระบุ ซึ่งมีประโยชน์สำหรับการตอบสนองต่อ attribute หรือ class:

/* ใช้เมื่อ host element มี attribute highlight */
:host([highlight]) {
background: #fef08a;
border-color: #ca8a04;
}
/* ใช้เมื่อ host element มี class .large */
:host(.large) {
font-size: 1.25rem;
}

เมื่อ event เกิดขึ้นภายใน shadow tree และฟอง (bubble) ออกไปสู่ light DOM browser จะทำ event retargetingevent.target จะถูกเปลี่ยนเป็น host element แทนที่จะเป็น element จริงภายใน shadow tree ซึ่งป้องกันไม่ให้โค้ดภายนอกเห็น internal structure

Light DOM คือเนื้อหาที่วางไว้ภายใน element จากภายนอก — เนื้อหาที่ส่งเป็น children ให้ custom element สามารถ project เนื้อหา light DOM เข้าสู่ shadow tree ได้โดยใช้ <slot> elements

ตัวเลือกBenefitCost
Event retargeting ที่ shadow boundaryโค้ดภายนอกไม่เห็น internal structure ของ component ผ่าน event.targetdebug event ยากขึ้น เพราะ event.target ที่ host ไม่ใช่ element จริงที่ถูกคลิกภายใน shadow tree
สไตล์ host ผ่าน :host / :host() จากภายใน shadow CSScomponent ควบคุม box model ของตัวเองได้ (display, border) โดยไม่ต้องพึ่งสไตล์ภายนอกโค้ดภายนอกยังคง override บาง property จาก host element ได้ (เช่น inline style) ทำให้ผลลัพธ์ขึ้นกับใครเขียนทีหลัง
  • คาดหวังว่า event.target ในหน้าเว็บจะชี้ไปที่ element จริงภายใน shadow tree — เพราะ event retargeting จะเปลี่ยน event.target ให้เป็น host element เสมอเมื่อ event ฟองออกมาถึง light DOM
  • ใช้ selector ธรรมดาแทน :host เพื่อสไตล์ตัว host element เอง — เขียน host-badge { border: ... } ใน shadow CSS แล้วสงสัยว่าทำไมไม่ทำงาน ต้องใช้ :host เท่านั้นเพราะ host element อยู่นอก shadow tree
  • สับสนระหว่าง light DOM กับ shadow DOM — คิดว่าเนื้อหาที่ project ผ่าน <slot> อยู่ใน shadow tree ทั้งที่จริงๆ light DOM content ยังคงเป็นของ caller และแก้ไขสไตล์จาก shadow root ไม่ได้โดยตรง

💡 ตัวอย่างจากของจริง

YouTube — video player component ใช้ event retargeting เพื่อให้โค้ดภายนอกจัดการ event ระดับ component (เช่น click ที่ player) โดยไม่ต้องรู้โครงสร้าง internal ของปุ่มควบคุมต่างๆ

Salesforce Lightning (LWC) — ใช้ :host styling อย่างเป็นระบบเพื่อให้ทุก component ควบคุม layout ของตัวเองได้โดยไม่ต้องพึ่ง global CSS ของหน้า

selector :host กำหนดเป้าหมายอะไร?
:host([disabled]) ใช้งานเมื่อใด?
CSS selector จากภายนอก shadow root สามารถกำหนดเป้าหมาย element ภายในได้หรือไม่?
light DOM คืออะไร?