ชื่อ 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 ได้แก่ แบบอักษร การประกาศพร็อพเพอร์ตี้ การค้นหาคอนเทนเนอร์ และล่าสุดคือการเปลี่ยนมุมมอง การจัดตำแหน่งจุดยึด และภาพเคลื่อนไหวที่ทำงานด้วยการเลื่อน ตารางต่อไปนี้ไม่ได้ครอบคลุมทั้งหมด แต่มีชื่อของรายการที่ 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 รายการจัดสไตล์องค์ประกอบเดียวกัน ระบบจึงระบุลําดับการแสดงผลตามลำดับต่อไปนี้
- ก่อนอื่น ให้ตรวจสอบสไตล์ภายในบริบทเงา รูปแบบนี้เป็นรูปแบบ "เริ่มต้น" ของชิ้นส่วน
- จากนั้นใช้รูปแบบภายนอกตามที่ระบุไว้ใน
::part
นี่คือสไตล์ "ที่กำหนดเอง" ของชิ้นส่วน - จากนั้นใช้สไตล์ภายในที่กําหนดไว้ร่วมกับ
!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 หลายรายการ โดยแต่ละรายการจะมุ่งเน้นที่ฟีเจอร์ใดฟีเจอร์หนึ่งและทดสอบสถานการณ์ 6 รูปแบบ ดังนี้
- การอ้างอิงภายนอกถึงชื่อภายนอก: ไม่มี Shadow DOM ที่เกี่ยวข้อง วิธีนี้น่าจะใช้ได้
- การอ้างอิงภายนอกถึงชื่อภายใน: การดำเนินการนี้ไม่ควรใช้งานได้ เนื่องจากจะหมายความว่าชื่อที่กําหนดไว้ในบริบทเงามีการรั่วไหล
- การอ้างอิงภายในถึงชื่อภายนอก: การดำเนินการนี้ควรใช้งานได้ เนื่องจากรูทเงาจะรับค่าชื่อระดับต้นไม้
- การอ้างอิงภายในถึงชื่อภายใน: การดำเนินการนี้ควรใช้งานได้ เนื่องจากทั้งชื่อการอ้างอิงอยู่ในขอบเขตเดียวกัน
- การอ้างอิง
::part
ไปยังชื่อภายนอก: การดำเนินการนี้ควรใช้งานได้ เนื่องจากทั้ง::part
และชื่อได้รับการประกาศในสโคปเดียวกัน ::part
การอ้างอิงชื่อภายใน: การดำเนินการนี้ไม่ควรทำงานเนื่องจากขอบเขตภายนอกไม่ควรได้รับข้อมูลเกี่ยวกับชื่อที่ประกาศภายใน Shadow DOM
@keyframes
ตามที่กำหนดไว้ในข้อกำหนด คุณควรอ้างอิงชื่อเฟรมหลักได้จากภายในรูทเงา ตราบใดที่ @keyframes
at-rule อยู่ในขอบเขตของบรรพบุรุษ ในทางปฏิบัติ ไม่มีเบราว์เซอร์ใดใช้ลักษณะการทำงานนี้ และคำจำกัดความของคีย์เฟรมจะอ้างอิงได้ในขอบเขตที่กำหนดเท่านั้น ดูปัญหา 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 พบว่าประสบการณ์การใช้งานไม่สอดคล้องกันและมีข้อบกพร่อง ไม่มีฟีเจอร์ใดที่เราตรวจสอบที่นี่ทำงานอย่างสอดคล้องกันในเบราว์เซอร์ต่างๆ และเป็นไปตามข้อกำหนด ข่าวดีคือความแตกต่างที่จะทำให้ประสบการณ์การใช้งานสอดคล้องกันนั้นมีจำนวนจำกัด นั่นคือรายการข้อบกพร่องและปัญหาเกี่ยวกับข้อกำหนด มาแก้ปัญหานี้กัน ในระหว่างนี้ เราหวังว่าภาพรวมนี้จะช่วยคุณได้หากพบปัญหาเกี่ยวกับความไม่สอดคล้องตามที่อธิบายไว้ในบทความนี้