من المفترض أن تعمل أسماء CSS المحدّدة من الناشر مع عنصر DOM المظلّل معًا. ومع ذلك، لا تتوافق المتصفحات مع المواصفات، وأحيانًا مع بعضها، ولا يتوافق كل اسم 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-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 في أشجار الظل في مواصفات CSS Scoping Level 1. باختصار: اسم CSS يكون عامًا داخل النطاق الذي تم تحديده فيه، ما يعني أنّه يمكن الوصول إليه من أشجار الظل للعناصر اللاحقة، ولكن ليس من أشجار الظل للعناصر الشقيقين أو العناصر السابقة. يُرجى العلم أنّ هذا يختلف عن الأسماء في منصة الويب، مثل أرقام تعريف العناصر، التي يتم تضمينها ضمن نطاق الشجرة نفسه.
استثناء من القاعدة: @property
على عكس أسماء CSS الأخرى، لا يتم تضمين سمات CSS في عنصر DOM الظلّي.
بل هي الطريقة الشائعة لتمرير المَعلمات في أشجار ظل مختلفة.
وهذا يجعل وصف
@property
مميّزًا: من المفترض أن يعمل مثل بيان نوع شامل للمستند يحدد كيفية عمل خاصية مُسمّاة معيّنة. وبما أنّه يجب أن تتطابق الخصائص
في أشجار الظل، سيؤدي عدم تطابق تعريفات الخصائص إلى توليد نتائج
غير متوقّعة، لذا يتم تحديد تعريفات @property
لتتم تسويتها وحلّها
وفقًا لترتيب المستند.
آلية عمل القاعدة مع ::part
أجزاء الظل:
تعرِض عنصرًا داخل شجرة ظلّ لشجرتها الرئيسية. من خلال إجراء ذلك، يمكن للشجيرة
الرئيسية الوصول إلى هذا العنصر وتصميمه أيضًا باستخدام العنصر ::part
.
بما أنّ ::part
يسمح لنطاقَي شجرة بتنسيق العنصر نفسه، يتم تحديد الترتيب التالي
للتسلسل:
- أولاً، تحقّق من النمط داخل سياق الظل. هذا هو النمط "التلقائي" للجزء.
- بعد ذلك، طبِّق النمط الخارجي كما هو محدّد في
::part
. هذا هو النمط "المخصّص" للجزء. - بعد ذلك، طبِّق أيّ نمط داخلي تمّ تحديده مع
!important
. يسمح ذلك للعنصر المخصّص بتحديد أنّ خاصية معيّنة لجزء معيّن لا يمكن تخصيصها باستخدام::part
.
وهذا يعني أنّه لا يمكن الإشارة إلى الأسماء من داخل shadow DOM من ::part
، لأنّ ::part
هو أسلوب على مستوى المضيف بدلاً من أسلوب على مستوى الظل. على سبيل المثال:
// 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;
}
آلية عمل القاعدة مع الأنماط المضمّنة
على عكس ::part
، يتمّ تطبيق الأنماط المضمّنة التي تحتوي على السمة style
، أو التي تضبط النمط باستخدام نصّ برمجي، على النطاق الذي ينطبق عليه العنصر. ويعود السبب في ذلك إلى أنّ تطبيق نمط على عنصر يتطلّب الوصول إلى
اسم معرِّف العنصر، وبالتالي إلى جذر الظل نفسه.
كيفية عمل أسماء CSS وShadow DOM معًا في الواقع
على الرغم من أنّ القواعد السابقة محدّدة ومتسقة، لا تعكس عمليات التنفيذ الحالية ذلك دائمًا.
من الناحية العملية، يعمل @property
بشكل مختلف عن المواصفات بطريقة موحّدة
على مستوى المتصفّحات، وتتضمن معظم الميزات الأخرى أخطاء مفتوحة (لم يتم طرح بعض الميزات
بعد، لذا يتوفّر الوقت لحلّها).
لاختبار هذه الميزات وشرح كيفية عملها، أنشأنا الصفحة التالية: https://css-names-in-the-shadow.glitch.me/. تحتوي هذه الصفحة على العديد من إطارات iframe، يركز كلّ منها على إحدى الميزات ويختبر ستة سيناريوهات:
- إشارة خارجية إلى اسم خارجي: لا يتضمّن ذلك DOM الظلّ، ومن المفترض أن يعمل هذا الإجراء بشكلٍ جيد.
- الإشارة الخارجية إلى اسم داخلي: من المفترض ألا يعمل هذا الإجراء، لأنّ ذلك قد يؤدي إلى تسرُّب الاسم المحدّد في سياق الظل.
- الإشارة الداخلية إلى الاسم الخارجي: من المفترض أن يكون هذا الإجراء ناجحًا، لأنّ الأسماء على مستوى الشجرة يتم اكتسابها من خلال جذور الظل.
- الإشارة الداخلية إلى الاسم الداخلي: من المفترض أن يكون هذا صحيحًا، لأنّ اسم الإشارة يقع في النطاق نفسه.
::part
يشير إلى الاسم الخارجي: من المفترض أن يعمل هذا الإجراء، لأنّه تمّت الإشارة إلى كلّ من::part
والاسم في النطاق نفسه.::part
الإشارة إلى الاسم الداخلي: من المفترض ألا يعمل هذا الإجراء، لأنّ النطاق الخارجي يجب ألا يحصل على معلومات عن الأسماء التي تمّ الإعلان عنها داخل DOM الظلّ.
@keyframes
وفقًا لما هو محدّد في المواصفات، من المفترض أن تتمكّن من الإشارة إلى أسماء الإطارات الرئيسية
من داخل جذر الظل، ما دامت قاعدة at-rule @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، تكون التجربة غير متّسقة وتمتلئ بالمشاكل. لا تعمل أي من الميزات التي فحصناها هنا بشكلٍ متسق على جميع المتصفّحات وفقًا للمواصفات. والخبر السارّ هو أنّ التغييرات التي يجب إجراؤها لجعل التجربة متّسقة هي قائمة محدودة بالأخطاء ومشاكل المواصفات. لنحاول حلّ هذه المشكلة. في هذه الأثناء، نأمل أن يساعدك هذا الملخّص إذا كنت تواجه الصعوبات المتعلّقة بال التناقضات الموضّحة في هذه المقالة.