Conditionally Apply CSS Based on At-Rule Support

ویژگی‌های وب: at-rule()‎

از @supports at-rule(@<at-rule name>) {…} برای اعمال مشروط برخی‌از قوانین یا اعلان‌های CSS استفاده کنید، فقط درصورتی‌که یک قانون at-rule خاص توسط مرورگر پشتیبانی شود. این می‌تواند شامل کل قوانین باشد یا در ترکیب با CSS تودرتو برای اعمال مشروط برخی‌از اظهارات استفاده شود.

.foo {
  background: var(--accent-color);

  @supports at-rule(@property) {
    background-image: var(--rainbow-gradient);
    animation: sliding-rainbow 1s linear infinite;
  }
}

از @supports at-rule() برای اعمال شرطی قانون at-rule شناسایی‌شده و نه چیز دیگری استفاده نکنید.

/* BAD: CSS already ignores rules the browser doesn't understand, so this is unnecessary */
@supports at-rule(@starting-style) {
  @starting-style {
    /* ... */
  }
}

تشخیص پشتیبانی از at-rules وقتی @supports at-rule() مناسب نیست

وقتی at-rule() گزینه‌ای نباشد، چه به‌دلیل پشتیبانی مرورگر یا به‌دلیل نیاز به تشخیص عمیق‌تر، می‌توانید از راهنمایی زیر استفاده کنید.

ابتدا ویژگی‌ها، مقادیر، یا انتخاب‌کننده‌ها را امتحان کنید

@supports can already detect properties, values, and selectors (via @supports selector(...)). In many cases, you can use these to detect support for a feature without needing to check for the at-rule itself.

برای مثال، به‌جای @supports at-rule(@function) برای شناسایی پشتیبانی از توابع سفارشی، می‌توانید از @supports (color: --foo()) استفاده کنید.

در موارد دیگر، ممکن است شبه‌کلاس‌ها یا شبه‌عناصری وجود داشته باشند که فقط زمانی دردسترس هستند که یک at-rule خاص پشتیبانی شود، که می‌تواند برای تشخیص پشتیبانی استفاده شود.

تشخیص انواع پُرسمان محتوا

at-rule() ONLY allows detection of at-rules by name. این ویژگی امکان تشخیص نحو یا توصیف‌کننده‌های دیگر را فراهم نمی‌کند. برای مثال، این مورد کار نخواهد کرد:

@supports at-rule(@container style(--a: 1)) {
  /* ... */
}

برای بسیاری‌از انواع پرسمان‌های محفظه، می‌توانید از container-type با مقدار مناسب استفاده کنید. برای مثال، @supports (container-type: scroll-state) برای پُرسمان‌های scroll-state یا پُرسمان‌های @supports (container-type: size)container-type: anchoredforanchored()‎.

اما برای پُرسمان‌های سبک، container-type وجود ندارد. مهم: برای تشخیص پشتیبانی از پُرسمان‌های سبک، از @supports (container-type: style) استفاده نکنید، زیرا این کار مؤثر نخواهد بود.

درعوض، می‌توانید پُرسمان سبکی را امتحان کنید که همیشه درست است:

@container style(--a: 1) or (not (style(--a: 1))) {
  /* Rules here will only be applied if style queries are supported */
}

این در هر مرورگری که از پُرسمان‌های سبک پشتیبانی می‌کند مطابقت خواهد داشت، صرف‌نظر از اینکه از چه نام یا مقدار ویژگی‌ای استفاده می‌کنید، به‌شرطی که در هر دو یکسان باشند.

دارایی‌های سفارشی ثبت‌شده (@property)

در برخی موارد، اگر CSS شرطی برای اعمال بتواند به یک ویژگی واحد کاهش یابد، می‌توانید از یک ویژگی سفارشی اختصاصی ثبت‌شده برای این منظور استفاده کنید:

/* Use a custom property to conditionally include the dash animation */
@property --progress-dash-animation {
  syntax: "*";
  inherits: false;
  initial-value: , progress-dash 3s ease-in-out infinite;
}

.spinner {
  /* The dash animation is only included if @property is supported */
  animation:
    progress-spin var(--_used-spinner-duration) linear infinite
    var(--progress-dash-animation, );
}

برای راه‌حل عمومی‌تر، می‌توانید یک ویژگی غیروراثتی را ثبت کنید و آن را روی (یک فاصله) در عنصر ریشه تنظیم کنید:

{# Testcase: https://codepen.io/leaverou/pen/KwWzpVr #}

@property --supports-atproperty {
    syntax: "*";
    inherits: false;
}

:root {
    --supports-atproperty: ;
}

body {
  /* The background is only applied if @property is supported */
    background: var(--supports-atproperty, green);
}

نکته‌ها:

  • هر دو این موارد فقط درصورتی کار می‌کنند که فاصله سفید جایگزین قابل‌قبولی باشد. برای موارد دیگر، باید از JS همان‌طور که در زیر توضیح داده شده است استفاده کنید.
  • راه‌حل همه‌منظوره به عدم وراثت بستگی دارد، بنابراین برای اعلان‌ها در عنصر ریشه کار نخواهد کرد.

استفاده از جاوا اسکریپت به‌عنوان آخرین راه‌حل

برای کل at-rules، وجود میاناهای خاصی را در جاوا اسکریپت بررسی کنید. برای مثال، اگر globalThis.CSSFunctionRule تعریف شده باشد، از @function پشتیبانی می‌شود.

اگر لازم است عمیق‌تر آزمایش کنید (مثلاً برای برخی مقدمه‌ها، قوانین تودرتو، توصیف‌کننده‌ها)، می‌توانید آزمایشی راه‌اندازی کنید و نحوه تجزیه آن را بررسی کنید:

const sheet = new CSSStyleSheet();
sheet.replaceSync(`
  @page {
    @top-left {
      content: "test";
    }
  }
`);
const SUPPORTS_PAGE_MARGINS = Boolean(sheet.cssRules[0]?.cssRules?.[0]);

مهم:

  • هنگام استفاده از جاوااسکریپت برای تشخیص پشتیبانی از ویژگی‌های CSS، سبک‌ها را مستقیماً از جاوااسکریپت اعمال نکنید. درعوض، کلاسی را به عنصر ریشه اعمال کنید و آن را در CSS منشعب کنید.
  • توجه داشته باشید که پرسمان‌های محفظه حتی اگر مقدمه تشخیص داده نشود تجزیه می‌شوند و هیچ راهی برای تشخیص پشتیبانی از انواع خاصی از پرسمان‌های محفظه از ساختار CSSOM وجود ندارد.
  • از CSS.registerProperty برای تشخیص پشتیبانی از @property استفاده نکنید زیرا پشتیبانی آن کمی گسترده‌تر است.

راهبردهای جایگزین

مگر اینکه این در هدف پشتیبانی شما باشد، فقط از @supports (at-rule()) برای شناسایی at-rules که پشتیبانی از آن‌ها محدودتر از خود ویژگی @supports (at-rule()) است استفاده کنید.

برای اعمال CSS به‌صورت شرطی براساس پشتیبانی از قوانین at-rules که قبل‌از این ویژگی ارائه شده‌اند، از راهنمایی‌های بخش بالا استفاده کنید.

برای تشخیص پشتیبانی از ویژگی @supports at-rule() به‌خودی‌خود، می‌توانید از یک قانون at استفاده کنید که تضمین شده است در همه مرورگرهایی که از @supports at-rule() پشتیبانی می‌کنند، مانند @supports at-rule(@media) { ... }، وجود داشته باشد.