ชื่อ CSS ที่ผู้เขียนกำหนดและ Shadow DOM: เป็นไปตามข้อกำหนดและในทางปฏิบัติ

ชื่อ CSS ที่ผู้ใช้กำหนดและ Shadow DOM ควรทำงานร่วมกัน อย่างไรก็ตาม เบราว์เซอร์ไม่สอดคล้องกับข้อกำหนด และบางครั้งก็ใช้ชื่อ CSS ที่ไม่สอดคล้องกัน และชื่อ CSS แต่ละชื่อก็มีความไม่สอดคล้องกันเล็กน้อย

บทความนี้จะบันทึกสถานะปัจจุบันของลักษณะการทํางานของชื่อ CSS ที่กําหนดโดยผู้เขียนในขอบเขตเงา โดยหวังว่าบทความนี้จะใช้เป็นแนวทางในการปรับปรุงความสามารถในการทำงานร่วมกันในอนาคตอันใกล้

ชื่อ CSS ที่ผู้เขียนกำหนดคืออะไร

ชื่อ CSS ที่นักเขียนกำหนดเป็นกลไกไวยากรณ์ CSS ที่ค่อนข้างเก่า ซึ่งเดิมทีมีไว้สำหรับกฎ @keyframes ซึ่งกำหนด <keyframe-name> เป็นตัวระบุที่กำหนดเองหรือสตริง แนวคิดนี้มีไว้เพื่อประกาศบางอย่างในส่วนหนึ่งของสไตล์ชีต แล้วอ้างอิงในส่วนอื่น

/* "fade-in" is a CSS name, representing a set of keyframes */
@keyframes fade-in {
  from { opacity: 0 };
  to { opacity: 1 }
}

.card {
  /* "fade-in" is a reference to the above keyframes */
  animation-name: fade-in;
}

ฟีเจอร์อื่นๆ ของ CSS ที่ใช้ชื่อ CSS ได้แก่ แบบอักษร การประกาศพร็อพเพอร์ตี้ การค้นหาคอนเทนเนอร์ และการเปลี่ยนมุมมองล่าสุด การกำหนดตำแหน่ง Anchor และภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน ตารางต่อไปนี้ไม่ได้ครอบคลุมทั้งหมด แต่มีชื่อของรายการที่ Chrome ตรวจสอบสถานะ

ฟีเจอร์ การประกาศชื่อ การอ้างอิงชื่อ
คีย์เฟรม @keyframes animation-name
แบบอักษร @font-face { }
@font-palette-values
font-family
font-palette
การประกาศพร็อพเพอร์ตี้ @property
การประกาศพร็อพเพอร์ตี้ที่กำหนดเองซึ่งไม่ได้ลงทะเบียน
var()
ดูการเปลี่ยน view-transition-name
view-transition-class
องค์ประกอบจำลอง ::view-transition-* รายการ
ตำแหน่งของ Anchor anchor-name position-anchor
ภาพเคลื่อนไหวแบบเลื่อน view-timeline-name
scroll-timeline-name
animation-timeline
รูปแบบรายการ @counter-style list-style
ตัวนับ counter-reset
counter-set
counter-increment
การค้นหาคอนเทนเนอร์ container-name @container
หน้าเว็บ page @page

จากที่เห็นในตาราง โดยทั่วไปชื่อ CSS จะมีการอ้างอิง CSS ที่สอดคล้องกัน เช่น animation-name เป็นการอ้างอิงถึงชื่อ @keyframes ชื่อ CSS แตกต่างจากชื่อที่กำหนดไว้ใน DOM เช่น แอตทริบิวต์และชื่อแท็ก เนื่องจากมีการประกาศแล้วอ้างอิงภายในบริบทของสไตล์ชีต

ความสัมพันธ์ของชื่อกับ Shadow DOM

แม้ว่าชื่อ CSS จะสร้างขึ้นเพื่อสร้างความสัมพันธ์ระหว่างส่วนต่างๆ ของเอกสารหรือสไตล์ชีต แต่ Shadow DOM สร้างขึ้นเพื่อทําตรงข้ามกัน โดยจะรวมความสัมพันธ์ไว้เพื่อไม่ให้ความสัมพันธ์ดังกล่าวแสดงในคอมโพเนนต์เว็บที่ควรจะเป็นเนมสเปซของตัวเอง

การนำชื่อ CSS และ Shadow DOM มารวมกันจะทำให้ประสบการณ์การคอมโพสิทคอมโพเนนต์เว็บมีความยืดหยุ่นมากพอ แต่ก็มีข้อจำกัดมากพอที่จะคงเสถียร

แนวคิดนี้ฟังดูดี ในทางปฏิบัติ เบราว์เซอร์ไม่สอดคล้องกับวิธีที่ชื่อ CSS ทำงานร่วมกับ Shadow DOM ทั้งระหว่างฟีเจอร์ในเบราว์เซอร์เดียวกัน ในเบราว์เซอร์ต่างๆ และระหว่างฟีเจอร์และข้อกำหนด

วิธีที่ชื่อและ Shadow DOM ควรทํางานร่วมกัน

ในการทำความเข้าใจปัญหานี้ คุณควรทำความเข้าใจว่า CSS ส่วนต่างๆ เหล่านี้ควรทำงานร่วมกันในเชิงทฤษฎีอย่างไร

กฎทั่วไป

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

ข้อยกเว้นสำหรับกฎ: @property

พร็อพเพอร์ตี้ CSS ไม่ได้อยู่ภายใน Shadow DOM ต่างจากชื่อ CSS อื่นๆ แต่เป็นเพียงวิธีทั่วไปในการส่งพารามิเตอร์ไปยัง Shadow Tree ต่างๆ สิ่งนี้ทำให้ข้อบ่งชี้ @property พิเศษ: เนื่องจากควรทํางานเหมือนการประกาศประเภทระดับเอกสารที่กําหนดวิธีทํางานของพร็อพเพอร์ตี้ที่มีชื่อหนึ่งๆ เนื่องจากพร็อพเพอร์ตี้ต้องตรงกันทั่วทั้งต้นไม้เงา การประกาศพร็อพเพอร์ตี้ที่ไม่ตรงกันจะทำให้เกิดผลลัพธ์ที่ไม่คาดคิด ดังนั้นจึงมีการระบุการประกาศ @property ให้ยุบและแก้ไขตามลําดับเอกสาร

วิธีที่กฎควรทํางานกับ ::part

ชิ้นส่วนเงาจะแสดงองค์ประกอบภายในต้นไม้เงาต่อต้นไม้หลัก ซึ่งจะทำให้ต้นไม้หลักเข้าถึงองค์ประกอบนั้นได้และจัดรูปแบบโดยใช้องค์ประกอบ ::part ด้วย

เนื่องจาก ::part อนุญาตให้สโคปต้นไม้ 2 รายการจัดสไตล์องค์ประกอบเดียวกันได้ ระบบจึงระบุลําดับการแสดงผลตามลำดับต่อไปนี้

  1. ก่อนอื่น ให้ตรวจสอบสไตล์ภายในบริบทเงา รูปแบบนี้เป็นรูปแบบ "เริ่มต้น" ของชิ้นส่วน
  2. จากนั้นใช้รูปแบบภายนอกตามที่ระบุไว้ใน ::part นี่เป็นรูปแบบ ที่ "กำหนดเอง" ของชิ้นส่วน
  3. จากนั้นใช้สไตล์ภายในที่กําหนดไว้ร่วมกับ !important การดำเนินการนี้ช่วยให้องค์ประกอบที่กำหนดเองประกาศว่า ::part ปรับแต่งพร็อพเพอร์ตี้บางอย่างของส่วนหนึ่งๆ ไม่ได้

ซึ่งหมายความว่าชื่อจากภายใน Shadow DOM จะอ้างอิงจาก ::part ไม่ได้ เนื่องจาก ::part เป็นสไตล์ระดับโฮสต์ ไม่ใช่สไตล์ระดับ Shadow เช่น

// inside the shadow DOM:
@keyframes fade-in {
  from { opacity: 0}
}

// This shouldn't work!
// The host style shouldn't know the name "fade-in"
::part(slider) {
  animation-name: fade-in;  
}

วิธีที่กฎควรทำงานร่วมกับสไตล์ในบรรทัด

สไตล์อินไลน์ที่มีแอตทริบิวต์ style หรือการตั้งค่ารูปแบบโดยใช้สคริปต์แบบเป็นโปรแกรมจะกำหนดขอบเขตไปยังบริเวณที่มีการกำหนดขอบเขตองค์ประกอบ ซึ่งต่างจาก ::part เนื่องจากหากต้องการใช้สไตล์กับองค์ประกอบ คุณต้องมีสิทธิ์เข้าถึงแฮนเดิลองค์ประกอบ และรูทเงา

วิธีที่ชื่อ CSS และ Shadow DOM ทำงานร่วมกันในความเป็นจริง

แม้ว่ากฎข้างต้นจะชัดเจนและสอดคล้องกัน แต่การใช้งานในปัจจุบันอาจไม่เป็นไปตามกฎดังกล่าวเสมอไป ในทางปฏิบัติ @property ทำงานแตกต่างจากข้อกำหนดในลักษณะที่สอดคล้องกันในเบราว์เซอร์ต่างๆ และฟีเจอร์อื่นๆ ส่วนใหญ่ยังมีข้อบกพร่องอยู่ (บางฟีเจอร์ยังไม่ได้เปิดตัว จึงมีเวลาแก้ไข)

เราได้สร้างหน้าต่อไปนี้เพื่อทดสอบและสาธิตวิธีการทำงานของฟีเจอร์เหล่านี้จริง https://css-names-in-the-shadow.glitch.me/ หน้านี้มี iframe หลายรายการ โดยแต่ละ iframe จะมุ่งเน้นฟีเจอร์ใดฟีเจอร์หนึ่งและทำการทดสอบ 6 สถานการณ์ต่อไปนี้

  • การอ้างอิงภายนอกถึงชื่อภายนอก: ไม่มี Shadow DOM ที่เกี่ยวข้อง วิธีนี้น่าจะใช้ได้
  • การอ้างอิงภายนอกไปยังชื่อภายใน: ไม่ควรทำงานเนื่องจากหมายความว่าชื่อที่กำหนดไว้ในบริบทเงาหลุด
  • การอ้างอิงภายในถึงชื่อภายนอก: การดำเนินการนี้ควรใช้งานได้ เนื่องจากรูทเงาจะรับค่าชื่อระดับต้นไม้
  • การอ้างอิงภายในถึงชื่อภายใน: การดำเนินการนี้ควรใช้งานได้ เนื่องจากทั้งชื่อการอ้างอิงอยู่ในขอบเขตเดียวกัน
  • ::part อ้างอิงถึงชื่อด้านนอก: ควรใช้งานได้ เนื่องจากทั้ง ::part และชื่อได้รับการประกาศไว้ในขอบเขตเดียวกัน
  • ::part การอ้างอิงชื่อภายใน: การดำเนินการนี้ไม่ควรทำงานเนื่องจากขอบเขตภายนอกไม่ควรได้รับข้อมูลเกี่ยวกับชื่อที่ประกาศภายใน Shadow DOM

@keyframes

ตามที่ระบุไว้ในข้อกำหนด คุณควรจะอ้างอิงชื่อคีย์เฟรมจากภายในรากเงาได้ ตราบใดที่กฎ at @keyframes อยู่ในขอบเขตระดับบน ในทางปฏิบัติจะไม่มีเบราว์เซอร์ใดใช้ลักษณะการทำงานนี้ และจะอ้างอิงคำจำกัดความคีย์เฟรมได้ในขอบเขตที่มีการกำหนดไว้เท่านั้น ดูปัญหา 10540

@property

ตามที่ระบุไว้ในข้อกำหนด การประกาศ @property ทั้งหมดจะรวมอยู่ในขอบเขตของเอกสาร แต่ในปัจจุบัน คุณประกาศ @property ได้เฉพาะในสโกปเอกสารในเบราว์เซอร์ทุกประเภท และระบบจะไม่สนใจการประกาศ @property ภายในรูทเงา
ดูปัญหา 10541

ข้อบกพร่องเฉพาะเบราว์เซอร์

ฟีเจอร์อื่นๆ แสดงลักษณะการทำงานที่ไม่สอดคล้องกันในเบราว์เซอร์ต่างๆ

  • @font-face จะยุบเป็นขอบเขตรูทใน Safari
  • Chromium ไม่อนุญาตให้รับค่ากฎ anchor-name ในรูทเงา
  • scroll-timeline-name และ view-timeline-name ไม่ได้กําหนดขอบเขตอย่างถูกต้องใน ::part (และใน Chromium ด้วย)
  • ไม่มีเบราว์เซอร์ใดอนุญาตให้ประกาศ @font-palette-values ในรูทเงา
  • view-transition-class สามารถกําหนดภายในรูทเงา (ทรานซิชันอยู่นอกรูทเงา)
  • Firefox อนุญาตให้ ::part เข้าถึงชื่อเงาภายใน (คำค้นหาคอนเทนเนอร์ คีย์เฟรม)
  • Firefox และ Safari ไม่สนใจ @counter-style ในรูทเงา

โปรดทราบว่า counter-reset, counter-set, counter-increment มีกฎที่ต่างกันเล็กน้อยเนื่องจากเป็นชื่อที่ระบุโดยนัย และการประกาศพร็อพเพอร์ตี้ CSS มีชุดกฎที่กำหนดไว้และผ่านการทดสอบมาอย่างดี

บทสรุป

ข่าวร้ายคือเมื่อตรวจสอบภาพรวมสถานะการทำงานร่วมกันในปัจจุบันเกี่ยวกับชื่อ CSS และ Shadow DOM พบว่าประสบการณ์การใช้งานไม่สอดคล้องกันและมีข้อบกพร่อง ไม่มีฟีเจอร์ใดที่เราตรวจสอบที่นี่ทำงานอย่างสอดคล้องกันในเบราว์เซอร์ต่างๆ และเป็นไปตามข้อกำหนด ข่าวดีคือความแตกต่างที่จะทำให้ประสบการณ์การใช้งานสอดคล้องกันนั้นมีจำนวนจำกัด นั่นคือรายการข้อบกพร่องและปัญหาเกี่ยวกับข้อกำหนด มาแก้ปัญหานี้กัน ในระหว่างนี้ เราหวังว่าภาพรวมนี้จะช่วยคุณได้หากพบปัญหาความไม่สอดคล้องตามที่อธิบายไว้ในบทความนี้