نامهای 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 | هر ملک سفارشی |
مشاهده انتقال | view-transition-name view-transition-class | ::view-transition-group() |
موقعیت یابی لنگر | anchor-name | position-anchor |
انیمیشن اسکرول محور | animation-timeline | view-timeline-name scroll-timeline-name |
سبک کانتر | @counter-style Counter-reset counter-set counter-increment | list-style |
پرس و جوهای کانتینر | container-name | @container |
متغیر CSS | --something | var(--something) |
صفحه | @page |
همانطور که در جدول می بینید، یک نام CSS معمولا دارای یک مرجع CSS مربوطه است. به عنوان مثال، animation-name
اشاره ای به نام @keyframes
است. نامهای CSS با نامهایی که در DOM تعریف شدهاند، مانند ویژگیها و نامهای تگ، متفاوت هستند، زیرا اعلام میشوند و سپس در متن شیوهنامهها ارجاع میشوند.
نحوه ارتباط نام ها با سایه DOM
در حالی که نامهای CSS برای ایجاد روابط بین بخشهای مختلف یک سند یا شیوه نامه ساخته شدهاند، Shadow DOM برای انجام برعکس ساخته شده است. این روابط را محصور می کند تا در اجزای وب که قرار است فضای نام خاص خود را داشته باشند، نشت نکنند.
با کنار هم قرار دادن نامهای CSS و DOM سایهای، تجربه ایجاد کامپوننتهای وب باید به اندازهای واضح باشد که انعطافپذیر باشد، اما به اندازه کافی محدود باشد تا پایدار باشد.
این در تئوری خوب است. در عمل، مرورگرها در نحوه تعامل نامهای CSS با DOM سایه، هم بین ویژگیهای یک مرورگر، در بین مرورگرها و هم بین ویژگیها و مشخصات، ناسازگار هستند.
چگونه نام ها و سایه DOM باید با هم کار کنند
برای درک مشکل، ارزش درک این را دارد که چگونه این بخشهای CSS باید در تئوری با هم کار کنند.
قاعده کلی
قاعده کلی نحوه رفتار نام های CSS در درخت های سایه در مشخصات محدوده سطح 1 CSS تعریف شده است. به طور خلاصه: یک نام CSS در محدوده ای که در آن تعریف شده است جهانی است، به این معنی که می توان از درختان سایه اولاد به آن دسترسی داشت، اما نه از درختان سایه برادر یا اجداد. توجه داشته باشید که این برخلاف نامهای موجود در پلتفرم وب مانند شناسههای عنصر است که در محدوده درختی یکسانی قرار میگیرند.
استثنا از قاعده: @property
برخلاف دیگر نامهای CSS، ویژگیهای CSS توسط Shadow DOM کپسوله نمیشوند . در عوض، آنها ابزار رایجی برای انتقال پارامترها به درختان سایه مختلف هستند. این ویژگی توصیفگر @property
را خاص میکند: قرار است مانند یک اعلان نوع سند-کلی رفتار کند که نحوه عملکرد یک ویژگی خاص با نام را مشخص میکند. از آنجایی که ویژگیها باید با درختهای سایه مطابقت داشته باشند، عدم تطابق اعلانهای دارایی نتایج غیرمنتظرهای ایجاد میکند، بنابراین اعلانهای @property
مشخص میشوند تا با توجه به ترتیب سند، مسطح و حل شوند.
چگونه قانون باید با ::part
کار کند
قسمت های سایه عنصری را در داخل درخت سایه در معرض درخت مادر قرار می دهد. با انجام این کار، درخت والد می تواند به آن عنصر دسترسی داشته باشد و همچنین با استفاده از عنصر ::part
به آن استایل دهد.
از آنجایی که ::part
به دو محدوده درختی اجازه می دهد تا به یک عنصر استایل دهند، ترتیب آبشاری زیر مشخص می شود:
- ابتدا استایل داخل زمینه سایه را بررسی کنید. این سبک "پیش فرض" قسمت است.
- سپس، استایل خارجی را همانطور که در
::part
تعریف شده اعمال کنید. این سبک "سفارشی" قطعه است. - سپس، هر سبک داخلی را که همراه با
!important
تعریف شده است، اعمال کنید. این به یک عنصر سفارشی اجازه می دهد تا اعلام کند که یک ویژگی خاص از یک قسمت خاص توسط::part
قابل تنظیم نیست.
این بدان معنی است که نامهای داخل 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 و سایه DOM در واقعیت
اگرچه قوانین قبلی به خوبی تعریف شده و سازگار هستند، پیاده سازی های فعلی همیشه منعکس کننده آن نیستند. در عمل، @property
به روشی ثابت در بین مرورگرها متفاوت از مشخصات کار می کند، و بیشتر ویژگی های دیگر دارای باگ های باز هستند (بعضی از آنها هنوز منتشر نشده اند، بنابراین زمان برای رفع آنها وجود دارد).
برای آزمایش و نشان دادن نحوه عملکرد این ویژگیها در عمل، صفحه زیر را ایجاد کردهایم: https://css-names-in-the-shadow.glitch.me/ . این صفحه دارای چندین iframe است که هر کدام بر روی یکی از ویژگی ها متمرکز شده و شش سناریو را آزمایش می کند:
- ارجاع بیرونی به نام بیرونی : DOM سایه ای درگیر نیست، این باید کار کند.
- ارجاع بیرونی به یک نام داخلی : این نباید کار کند، زیرا به این معنی است که نام تعریف شده در زمینه سایه لو رفته است.
- ارجاع درونی به نام بیرونی : این باید کار کند، زیرا نام های دارای دامنه درختی توسط ریشه های سایه به ارث می رسند.
- ارجاع داخلی به نام داخلی : این باید کار کند، زیرا هر دو نام مرجع در یک محدوده هستند.
-
::part
به نام بیرونی : این باید کار کند، زیرا هر دو::part
و نام در یک محدوده اعلام شده اند. -
::part
به نام داخلی : این نباید کار کند، زیرا محدوده بیرونی نباید در مورد نام های اعلام شده در سایه DOM اطلاعات کسب کند.
@keyframes
همانطور که در مشخصات تعریف شده است، تا زمانی که @keyframes
at-rule در یک محدوده اجدادی باشد، باید بتوانید به نامهای فریم کلیدی از درون یک ریشه سایه ارجاع دهید. در عمل، هیچ مرورگری این رفتار را پیادهسازی نمیکند، و تعاریف فریم کلیدی را فقط میتوان در محدودهای که در آن تعریف شدهاند ارجاع داد. به شماره 10540 مراجعه کنید.
@property
همانطور که در مشخصات تعریف شده است، هرگونه اعلامیه @property
به محدوده سند مسطح می شود. با این حال، امروزه در همه مرورگرها فقط میتوانید @property
در محدوده سند اعلام کنید و اعلانهای @property
در ریشههای سایه نادیده گرفته میشوند.
به شماره 10541 مراجعه کنید.
اشکالات خاص مرورگر
سایر ویژگیها رفتار ثابتی را در مرورگرها نشان نمیدهند:
-
@font-face
در سافاری تا محدوده ریشه پهن شده است. - Chromium به ارث بردن قوانین
@anchor-name
در ریشه سایه اجازه نمی دهد -
@scroll-timeline-name
و@view-timeline-name
به درستی در::part
(همچنین در Chromium) مشخص نشدهاند. - هیچ مرورگری اجازه نمی دهد
@font-palette-values
در ریشه های سایه اعلام کند. -
view-transition-class
می توان در داخل یک ریشه سایه تعریف کرد (خود انتقال خارج از shadow-root است). - فایرفاکس به
::part
اجازه می دهد تا به نام های سایه داخلی (پرس و جوهای کانتینر، فریم های کلیدی) دسترسی پیدا کند. - فایرفاکس و سافاری به
@counter-style
در ریشه سایه احترام نمی گذارند.
توجه داشته باشید که counter-reset
، counter-set
، counter-increment
قوانین کمی متفاوت دارند زیرا نامهای ضمنی هستند و اعلان ویژگیهای CSS دارای مجموعهای از قوانین ثابت و آزمایششده است.
نتیجه گیری
خبر بد این است که هنگام بررسی عکس فوری از حالت interop فعلی با توجه به نامهای CSS و سایه DOM، تجربه ناسازگار و باگ است. هیچ یک از ویژگی هایی که در اینجا مورد بررسی قرار دادیم در بین مرورگرها و بر اساس مشخصات به طور مداوم رفتار نمی کنند. خبر خوب این است که دلتا برای سازگار کردن تجربه، لیست محدودی از اشکالات و مشکلات مشخصات است. بیایید این را درست کنیم! در عین حال، اگر با ناهماهنگی های توضیح داده شده در این مقاله دست و پنجه نرم می کنید، امیدواریم این مرور کلی بتواند به شما کمک کند.