مدیریت اولویت با معماری جدید: Cascade Layers

تا اینجا دیدیم که Specificity گاهی می‌تونه دردسرساز بشه؛ مخصوصاً وقتی چند بخش مختلف پروژه (مثل یک کتابخانه خارجی، کد خودمون، و Utility Classes) با هم سر اولویت رقابت می‌کنن. Cascade Layers دقیقاً برای حل همین مشکل طراحی شده و آخرین مفهوم مهم این فصله.

مشکلی که Cascade Layers حل می‌کند

فرض کن یه پروژه داری که هم از یه کتابخانه CSS خارجی استفاده می‌کنه (مثلاً یه Framework)، هم استایل‌های خودت رو داره. گاهی برای اینکه استایل خودت روی استایل Framework غلبه کنه، مجبور می‌شی Specificity رو مصنوعی بالا ببری یا حتی از !important استفاده کنی:

/* استایل Framework */
.button {
  background-color: gray;
}

/* استایل خودمان، مجبور به افزایش Specificity */
body .container .button {
  background-color: blue;
}

این روش کار می‌کنه، ولی کد رو کثیف و شکننده می‌کنه. Cascade Layers راه‌حلی تمیزتر برای همین مسئله ارائه می‌ده.

Cascade Layer چیست؟

Cascade Layer یک لایه مجزا برای گروه‌بندی Ruleهای CSS‌ه. نکته کلیدی اینه: اولویت بین لایه‌ها، کاملاً مستقل از Specificity داخل هر لایه تعیین می‌شه. لایه‌ای که دیرتر تعریف بشه، اولویت بالاتری نسبت به کل لایه‌های قبلی داره؛ حتی اگه Specificity Ruleهای داخلش پایین‌تر باشه.

نحوه تعریف یک Layer

برای تعریف یک لایه، از قانون @layer استفاده می‌شه:

@layer base {
  .button {
    background-color: gray;
    padding: 10px;
  }
}

@layer custom {
  .button {
    background-color: blue;
  }
}

تو این مثال، دو لایه به اسم base و custom تعریف شده. با اینکه هر دو Rule داخل این لایه‌ها Specificity یکسانی دارن (هردو یک Class Selector ساده)، چون لایه custom بعد از base تعریف شده، رنگ نهایی دکمه آبی خواهد بود.

نکته مهم: Specificity در Cascade Layers چه نقشی دارد؟

این بخش خیلی مهمه: وقتی چند Layer داریم، اول ترتیب Layerها بررسی می‌شه، نه Specificity داخل‌شون. یعنی حتی یک ID Selector قوی در یک Layer قبلی‌تر، نمی‌تونه روی یک Type Selector ساده در یک Layer بعدی‌تر غلبه کنه:

@layer base {
  #main-button {
    background-color: red;
  }
}

@layer custom {
  .button {
    background-color: blue;
  }
}

با اینکه #main-button از نظر Specificity بسیار قوی‌تر از .buttonه، چون لایه base زودتر از custom تعریف شده، رنگ نهایی همچنان آبی خواهد بود. این دقیقاً برعکس رفتاریه که بدون Layer انتظارش رو داشتیم.

ترتیب تعریف Layerها از قبل

می‌شه ترتیب اولویت Layerها رو، حتی قبل از نوشتن محتوای‌شون، از قبل مشخص کرد:

@layer reset, base, components, utilities;

این خط، فقط ترتیب اولویت رو تعریف می‌کنه (از پایین‌ترین به بالاترین اولویت): reset کمترین اولویت رو داره و utilities بیشترین. بعداً می‌تونیم محتوای هر لایه رو در هر جای فایل (حتی در فایل‌های جدا) پر کنیم:

@layer reset, base, components, utilities;

@layer reset {
  * {
    margin: 0;
    padding: 0;
  }
}

@layer components {
  .button {
    background-color: gray;
  }
}

@layer utilities {
  .button {
    background-color: green;
  }
}

در این مثال، حتی اگه ترتیب فیزیکی نوشتن Ruleها به‌هم بریزه، چون ترتیب Layerها از قبل با خط اول مشخص شده، اولویت نهایی همیشه طبق همون ترتیب اولیه (reset، base، components، utilities) خواهد بود.

Rule های بدون Layer کجا قرار می‌گیرند؟

هر Ruleای که خارج از هر @layerای نوشته بشه، به‌طور خودکار در بالاترین اولویت ممکن قرار می‌گیره؛ یعنی حتی بالاتر از آخرین Layer تعریف‌شده.

@layer base {
  p {
    color: gray;
  }
}

p {
  color: black;
}

در این مثال، Rule دوم (بدون Layer) روی Rule داخل base اولویت داره؛ پس رنگ نهایی مشکی خواهد بود.

ارتباط با revert-layer

همون‌طور که تو درس ۲-۵ دیدیم، کلیدواژه revert-layer دقیقاً برای همین ساختار طراحی شده؛ یعنی اجازه می‌ده مقدار یک Property رو به لایه قبلی برگردونیم، بدون اینکه از کل ساختار Cascade خارج بشیم.

چرا Cascade Layers مفید است؟

  • امکان مدیریت اولویت بین بخش‌های مختلف پروژه (مثل Reset، Framework، کد خودمان، Utility Classes) بدون نیاز به افزایش مصنوعی Specificity.
  • کاهش نیاز به استفاده از !important برای غلبه بر استایل‌های خارجی.
  • ساختار قابل‌پیش‌بینی‌تر، مخصوصاً در پروژه‌های بزرگ با چندین منبع CSS.

نکات مهم

  • اولویت بین Layerها، مستقل از Specificity داخل هر Layer تعیین می‌شه.
  • Layerای که دیرتر تعریف بشه، اولویت بالاتری نسبت به Layerهای قبلی داره.
  • Ruleهای خارج از هر Layer، همیشه بالاترین اولویت ممکن (بالاتر از همه Layerها) رو دارن.

اشتباهات رایج

  • تصور اینکه Specificity هنوز هم بین Layerهای مختلف تعیین‌کننده‌ست؛ در حالی که ترتیب Layer همیشه اولویت بالاتری داره.
  • فراموش کردن اینکه Ruleهای بدون Layer، به‌طور خودکار بالاترین اولویت رو می‌گیرن.

جمع‌بندی

Cascade Layers، از طریق قانون @layer، امکان گروه‌بندی Ruleهای CSS در لایه‌های مجزا با اولویت مشخص رو فراهم می‌کنه. اولویت بین Layerها کاملاً مستقل از Specificity داخل هر Layer تعیین می‌شه و Layerهای دیرتر تعریف‌شده، اولویت بالاتری دارن. این ابزار قدرتمند، مدیریت CSS در پروژه‌های بزرگ رو بسیار ساده‌تر می‌کنه و فصل دوم دوره رو با یک مفهوم کاملاً مدرن به پایان می‌رسونه.