نام های CSS تعریف شده توسط نویسنده و سایه DOM: در مشخصات و در عمل

نام‌های 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 به دو محدوده درختی اجازه می دهد تا به یک عنصر استایل دهند، ترتیب آبشاری زیر مشخص می شود:

  1. ابتدا استایل داخل زمینه سایه را بررسی کنید. این سبک "پیش فرض" قسمت است.
  2. سپس، استایل خارجی را همانطور که در ::part تعریف شده اعمال کنید. این سبک "سفارشی" قطعه است.
  3. سپس، هر سبک داخلی را که همراه با !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، تجربه ناسازگار و باگ است. هیچ یک از ویژگی هایی که در اینجا مورد بررسی قرار دادیم در بین مرورگرها و بر اساس مشخصات به طور مداوم رفتار نمی کنند. خبر خوب این است که دلتا برای سازگار کردن تجربه، لیست محدودی از اشکالات و مشکلات مشخصات است. بیایید این را درست کنیم! در عین حال، اگر با ناهماهنگی های توضیح داده شده در این مقاله دست و پنجه نرم می کنید، امیدواریم این مرور کلی بتواند به شما کمک کند.