{"id":"l-css-1-3","courseId":"css-mastery","lang":"ar","kind":"lesson","summary":"نظّم ملف الأنماط في طبقات cascade بحيث تفوز مجموعات الأنماط كاملة (إعادة الضبط والـ components والـ utilities) بحسب ترتيب الـ layers لا بحسب الـ specificity.","html":"<p>نما في ملف أنماط Waypoint أربعة أنواع من CSS: إعادة ضبط (reset)، وأنماط أساسية للعناصر، وcomponents مثل بطاقة الجلسة، وأدوات utilities ذات المهمّة الواحدة مثل <code dir=\"ltr\">.bg-accent</code> يرشّها فريق المحتوى في الـ HTML. يُفترض أن تفوز الـ utilities؛ فهذا هو الغرض منها أصلًا. لكن selector component مثل <code dir=\"ltr\">.schedule .session-card .badge</code> درجته (0,3,0)، والـ utility درجتها (0,1,0)، فتخسر الـ utility ويكتب أحدهم <code dir=\"ltr\">!important</code> من جديد.</p>\n<p>لم تُصمَّم الـ specificity قطّ للتعبير عن أن «هذه <em>المجموعة</em> من الأنماط أعلى رتبة من تلك». أما <strong>طبقات الـ cascade</strong> (cascade layers) فصُمِّمت لهذا بالضبط.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">أعلن الترتيب ثم املأ الـ layers</h2>\n<p>الـ layer (طبقة) وعاء مسمّى من القواعد. تعلن الترتيب مرة واحدة، في أعلى ملف الـ CSS:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">styles.css</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@layer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> reset</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">base</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">components</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">utilities</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span></code></pre></div>\n<p>ثم تضع القواعد في الـ layers، بأيّ ترتيب ومن أيّ ملف:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">CSS</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@layer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> components</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  .schedule</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> .session-card</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> .badge</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    background</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">#ede9fe</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    color</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">#5b21b6</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@layer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> utilities</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  .bg-accent</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">background</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">#fde68a</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>الآن تفوز <code dir=\"ltr\">.bg-accent</code> على خلفية الـ component رغم أن الـ specificity الخاصة بها أقل. حين يصل الـ cascade إلى الخطوة 3 (الـ layers) يرى أن التصريحين من layerين مختلفتين، فيختار المُعلنة لاحقًا، ولا يصل إلى الـ specificity أبدًا. أما داخل الـ layer الواحدة فتعمل الـ specificity وترتيب الظهور كما تعرفهما.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 640 300\" role=\"img\" aria-labelledby=\"l-css-1-3-t1\"><defs><marker id=\"arrow-l-css-1-3-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-css-1-3-t1\">طبقات مرصوصة من الأقل أولوية إلى الأعلى: reset ثم base ثم components ثم utilities، وفي القمة الأنماط خارج الـ layers. سهم على اليمين يشير إلى الأعلى بعنوان أولوية أعلى.</title>\n  <rect class=\"d-box\" x=\"60\" y=\"236\" width=\"400\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"80\" y=\"264\">@layer reset</text>\n  <rect class=\"d-box\" x=\"60\" y=\"184\" width=\"400\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"80\" y=\"212\">@layer base</text>\n  <rect class=\"d-box-primary\" x=\"60\" y=\"132\" width=\"400\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"80\" y=\"160\">@layer components</text>\n  <rect class=\"d-box-accent\" x=\"60\" y=\"80\" width=\"400\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"80\" y=\"108\">@layer utilities</text>\n  <rect class=\"d-box-warn\" x=\"60\" y=\"20\" width=\"400\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"80\" y=\"48\">أنماط خارج الـ layers</text>\n  <path class=\"d-arrow\" d=\"M500 276 L500 30\" marker-end=\"url(#arrow-l-css-1-3-1)\"/>\n  <text class=\"d-label\" x=\"516\" y=\"150\">أولوية</text>\n  <text class=\"d-label\" x=\"516\" y=\"172\">أعلى</text>\n</svg><figcaption>الـ layers اللاحقة تفوز في التصريحات العادية، والأنماط خارج الـ layers تجلس في القمة</figcaption></figure>\n<p>أول تعليمة <code dir=\"ltr\">@layer</code> هي التي تثبّت الترتيب. إن كتبت <code dir=\"ltr\">@layer utilities { … }</code> قبل أن تعلن <code dir=\"ltr\">components</code> أصلًا، تصبح utilities هي الـ layer <em>الأولى</em> (الأدنى). لهذا مكان تعليمة الترتيب في أعلى ملف الأنماط الرئيسي تمامًا.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">الأنماط خارج الـ layers تفوز</h2>\n<p>أيّ قاعدة عادية ليست داخل layer تذهب إلى layer ضمنية تتغلّب على كل الـ layers المسمّاة. يبدو هذا معكوسًا في البداية، لكنه ما يجعل تبنّي الـ layers ممكنًا: تستطيع تغليف الكود الجديد في layers اليوم، وتحتفظ الـ CSS الحالية غير المنتمية إلى layer بسلوكها كما هو.</p>\n<p>والوجه الآخر لهذا فخّ كلاسيكي.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>ترك الـ CSS القديمة خارج الـ layers</span></p>\n<p>تضع الـ components الجديدة في layers، فتظل قاعدة قديمة مثل <code dir=\"ltr\">h2 { color: black; }</code> من النموذج الأولي تتغلّب عليها، لأن ما هو خارج الـ layers يتغلّب على ما بداخلها. غلّف الـ CSS القديمة أو الخارجية في layer مبكرة خاصة بها، مثل <code dir=\"ltr\">@layer legacy, reset, base, components, utilities;</code>، لتخسر أمام كل ما تكتبه عن قصد.</p>\n</aside>\n<p>ويمكن وضع ملفات الأطراف الثالثة في layer مباشرةً عند استيرادها:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">CSS</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@layer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> vendor</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">reset</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">base</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">components</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">utilities</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@import</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> url</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"calendar-widget.css\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">layer</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">vendor</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span></code></pre></div>\n<p>لاحظ أن قواعد <code dir=\"ltr\">@import</code> يجب أن تأتي قبل أيّ قواعد أخرى باستثناء <code dir=\"ltr\">@charset</code> وتعليمات <code dir=\"ltr\">@layer</code>، ولهذا بالضبط تستطيع تعليمة الترتيب أن تجلس فوقها.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">التصريحات المهمّة تقلب الترتيب</h2>\n<p>في تصريحات <code dir=\"ltr\">!important</code> تنعكس أولوية الـ layers: القاعدة المهمّة في <code dir=\"ltr\">reset</code> تتغلّب على القاعدة المهمّة في <code dir=\"ltr\">utilities</code>، والقواعد المهمّة داخل الـ layers تتغلّب على المهمّة خارجها. وهذا يحاكي طريقة عمل المصادر (قاعدة المستخدم المهمّة تتغلّب على قاعدتك)، ويعطي الـ layers المنخفضة طريقة لحماية ما هو جوهري. تستطيع إعادة الضبط أن تثبّت <code dir=\"ltr\">[hidden] { display: none !important; }</code> فلا يستطيع أيّ component أن يُظهر محتوى مخفيًا بالخطأ.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">الـ layers المتداخلة والتراجع</h2>\n<p>يمكن أن تتداخل الـ layers: <code dir=\"ltr\">@layer components.cards { … }</code> تنشئ layer اسمها <code dir=\"ltr\">cards</code> داخل <code dir=\"ltr\">components</code>، وتُحسم أولويتها داخل الـ layer الأم. تستخدم الفرق هذا لإعطاء كل مجلد components طبقة فرعية خاصة به دون أن يتأثّر الترتيب العام.</p>\n<p>وهناك كلمة مفتاحية أخرى تعمل مع الـ layers: <code dir=\"ltr\">revert-layer</code>. ضبط <code dir=\"ltr\">color: revert-layer</code> يعيد الخاصية إلى ما كانت ستنتجه الـ layers السابقة، كأن تصريح هذه الـ layer غير موجود. وهي مفيدة في utility مثل <code dir=\"ltr\">.reset-color { color: revert-layer; }</code>.</p>\n<h2 id=\"sec-5\" tabindex=\"-1\">تبنّي الـ layers في قاعدة كود قائمة</h2>\n<p>لا تحتاج إلى إعادة كتابة. في قاعدة كود Waypoint استغرق الانتقال ظهيرة واحدة وثلاث خطوات:</p>\n<ol>\n<li>أضف تعليمة الترتيب في أعلى ملف الأنماط الرئيسي تمامًا، وضع layer اسمها <code dir=\"ltr\">legacy</code> أولًا.</li>\n<li>غلّف كل ملف موجود بـ <code dir=\"ltr\">@layer legacy { … }</code>، أو استورده بـ <code dir=\"ltr\">layer(legacy)</code>. لن يتغيّر شيء بصريًا، لأن القواعد القديمة ما زالت تتنافس فيما بينها تمامًا كما كانت.</li>\n<li>كلما لمست component، انقل قواعده من <code dir=\"ltr\">legacy</code> إلى <code dir=\"ltr\">components</code>. كل نقلة كهذه لا يمكن إلا أن تجعل كودك الجديد <em>أقوى</em> مقارنةً بالقديم، لا أضعف أبدًا.</li>\n</ol>\n<p>العائد يصل سريعًا: تتوقّف الـ components الجديدة عن الحاجة إلى selectors ثقيلة لتهزم القديمة، وتستطيع حذف تصريحات <code dir=\"ltr\">!important</code> واحدًا تلو الآخر كلما زال سببه.</p>\n<aside class=\"callout callout-note\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4\"/><path d=\"M12 8h.01\"/></svg><span><span class=\"callout-kind\">ملاحظة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>الدعم</span></p>\n<p>طبقات الـ cascade متاحة على نطاق واسع حسب Baseline (أي مدعومة في كل المتصفّحات الرئيسية منذ مدة كافية): كل المتصفّحات الحالية تدعمها منذ مطلع 2022. يمكنك إطلاقها بلا بديل احتياطي.</p>\n</aside>\n<h2 id=\"sec-6\" tabindex=\"-1\">دورك الآن</h2>\n<p>في التمرين، لشارة Waypoint selector component ثقيل وutility يجب أن تتجاوزه. ضع القواعد في layers لتفوز الـ utility دون تعديل أيّ selector ودون إضافة <code dir=\"ltr\">!important</code>. الـ layers تحسم «أيّ مجموعة تفوز»؛ والدرس التالي يتناول «أيّ قيمة»، باستخدام الـ custom properties كمقابض تكشفها الـ components لديك.</p>\n","toc":[{"id":"sec-1","text":"أعلن الترتيب ثم املأ الـ layers","level":2},{"id":"sec-2","text":"الأنماط خارج الـ layers تفوز","level":2},{"id":"sec-3","text":"التصريحات المهمّة تقلب الترتيب","level":2},{"id":"sec-4","text":"الـ layers المتداخلة والتراجع","level":2},{"id":"sec-5","text":"تبنّي الـ layers في قاعدة كود قائمة","level":2},{"id":"sec-6","text":"دورك الآن","level":2}],"takeaways":["أعلن ترتيب الـ layers مرة واحدة في الأعلى بـ <code dir=\"ltr\">@layer reset, base, components, utilities;</code>، والـ layers اللاحقة تفوز على السابقة بغضّ النظر عن الـ specificity.","الـ specificity ما زالت مهمة، لكن فقط بين التصريحات الموجودة داخل الـ layer نفسها.","الأنماط العادية التي لا تنتمي إلى أيّ layer تتغلّب على كل نمط داخل layer، لذا غلّف الـ CSS القديمة أو الخارجية في layer بدل أن تتركها طليقة.","<code dir=\"ltr\">!important</code> تعكس ترتيب الـ layers: التصريح المهمّ في layer مبكرة يتغلّب على التصريح المهمّ في layer لاحقة."],"further":[{"title":"@layer (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@layer"},{"title":"Cascade layers (MDN guide)","url":"https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Cascade_layers"},{"title":"A complete guide to CSS cascade layers (CSS-Tricks)","url":"https://css-tricks.com/css-cascade-layers/"}],"quiz":[{"q":"<p>ما الخلفية التي يأخذها <code dir=\"ltr\">.badge.sold-out</code>؟</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">CSS</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@layer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> components</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">utilities</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@layer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> utilities</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.sold-out</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">background</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">gold</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; } }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">@layer</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> components</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.schedule</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> .card</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> .badge</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">background</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">lavender</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; } }</span></span></code></pre></div>\n","options":[{"text":"lavender، لأن الـ selector الخاص بها أعلى specificity.","why":"الـ specificity لا تُقارَن إلا داخل الـ layer الواحدة. القاعدتان في layerين مختلفتين، لذا يحسم ترتيب الـ layers أولًا."},{"text":"lavender، لأن كتلة components تظهر لاحقًا في الملف.","why":"ترتيب الـ layers يأتي من أول تعليمة <code dir=\"ltr\">@layer</code>، لا من موضع ظهور كل كتلة."},{"text":"gold، لأن <code dir=\"ltr\">utilities</code> أُعلنت بعد <code dir=\"ltr\">components</code>.","why":"صحيح. الـ layers المُعلنة لاحقًا تفوز في التصريحات العادية، قبل أن تُستشار الـ specificity."}],"answer":2},{"q":"<p>أضفت <code dir=\"ltr\">@layer reset, components;</code> وغلّفت الكود، لكن قاعدة قديمة <code dir=\"ltr\">h2 { color: black; }</code> تقع خارج أيّ layer ما زالت تتجاوز عناوين الـ components لديك. لماذا؟</p>","options":[{"text":"الأنماط العادية خارج الـ layers أولويتها أعلى من كل الـ layers.","why":"صحيح. الأنماط غير المنتمية إلى layer تتصرّف كأنها layer أخيرة ضمنية. غلّف الـ CSS القديمة في layer مبكرة خاصة بها لتخفض رتبتها."},{"text":"selectors الأنواع تتغلّب دائمًا على القواعد داخل الـ layers.","why":"نوع الـ selector لا علاقة له بالأمر؛ أيّ selector خارج الـ layers، حتى <code dir=\"ltr\">*</code>، يتغلّب على القواعد داخلها في التصريحات العادية."},{"text":"يتجاهل المتصفّح <code dir=\"ltr\">@layer</code> حين يخلط الملف بين قواعد داخل الـ layers وخارجها.","why":"الخلط مدعوم بالكامل. يضع المتصفّح كل القواعد غير المنتمية إلى layer في layer ضمنية فوق الـ layers المسمّاة."},{"text":"قاعدة <code dir=\"ltr\">h2</code> تُحمَّل أولًا، فتُثبَّت.","why":"ترتيب الظهور آخر ما يكسر التعادل، وهنا تفصل الـ layers بين القاعدتين أصلًا."}],"answer":0},{"q":"<p>كيف تضع ملف أنماط من طرف ثالث في الـ layer الأقل أولوية؟</p>","options":[{"text":"<code dir=\"ltr\">@layer vendor { @import url(picker.css); }</code>","why":"لا يمكن أن تظهر <code dir=\"ltr\">@import</code> داخل كتلة layer؛ يجب أن تأتي تعليمات الاستيراد في أعلى ملف الأنماط."},{"text":"<code dir=\"ltr\">@import url(picker.css) layer(vendor);</code> بعد إعلان <code dir=\"ltr\">@layer vendor, base, components;</code>","why":"صحيح. الدالة <code dir=\"ltr\">layer()</code> على <code dir=\"ltr\">@import</code> تضع الملف كله في الـ layer المسمّاة، وتعليمة الترتيب تجعل تلك الـ layer أولى الطبقات."},{"text":"<code dir=\"ltr\">&lt;link rel=&quot;stylesheet&quot; href=&quot;picker.css&quot; layer=&quot;vendor&quot;&gt;</code>","why":"لا توجد سمة <code dir=\"ltr\">layer</code> على <code dir=\"ltr\">&lt;link&gt;</code>؛ وضع ملف في layer يكون عبر <code dir=\"ltr\">@import … layer()</code>."}],"answer":1},{"q":"<p>في layer اسمها <code dir=\"ltr\">components</code> يقول تصريح <code dir=\"ltr\">color: red !important</code>، وفي layer لاحقة اسمها <code dir=\"ltr\">utilities</code> يقول تصريح آخر <code dir=\"ltr\">color: blue !important</code>. أيّهما يفوز؟</p>","options":[{"text":"blue، لأن utilities هي الـ layer اللاحقة.","why":"هذه قاعدة التصريحات العادية. أما في التصريحات المهمّة فينقلب ترتيب الـ layers."},{"text":"red، لأن التصريحات المهمّة تعكس ترتيب الـ layers.","why":"صحيح. هذا الانعكاس يتيح لـ layer منخفضة (مثل إعادة الضبط) أن تحمي قيمة بـ <code dir=\"ltr\">!important</code> لا تستطيع الـ layers اللاحقة تجاوزها."},{"text":"صاحب الـ selector الأعلى specificity.","why":"ترتيب الـ layers يُحسم قبل الـ specificity دائمًا؛ والـ specificity لا تقارن إلا تصريحات من الـ layer نفسها."}],"answer":1}],"exercise":{"kind":"web","mode":"dom","starter":{"html":"<section class=\"schedule\">\n  <article class=\"session-card\">\n    <h2>Container Queries in Production</h2>\n    <span class=\"badge\">Layout</span>\n    <span class=\"badge bg-accent\">Sold out</span>\n  </article>\n</section>","css":"/* reset */\n* { box-sizing: border-box; }\nh2 { margin: 0 0 0.5rem; }\n\n/* components */\n.schedule .session-card .badge {\n  display: inline-block;\n  padding: 0.2em 0.7em;\n  border-radius: 999px;\n  background: #ede9fe;\n  color: #5b21b6;\n}\n\n/* utilities: these should always win */\n.bg-accent { background: #fde68a; }\n"},"solution":{"html":"<section class=\"schedule\">\n  <article class=\"session-card\">\n    <h2>Container Queries in Production</h2>\n    <span class=\"badge\">Layout</span>\n    <span class=\"badge bg-accent\">Sold out</span>\n  </article>\n</section>","css":"@layer reset, components, utilities;\n\n@layer reset {\n  * { box-sizing: border-box; }\n  h2 { margin: 0 0 0.5rem; }\n}\n\n@layer components {\n  .schedule .session-card .badge {\n    display: inline-block;\n    padding: 0.2em 0.7em;\n    border-radius: 999px;\n    background: #ede9fe;\n    color: #5b21b6;\n  }\n}\n\n@layer utilities {\n  .bg-accent { background: #fde68a; }\n}\n"},"checks":[{"id":"utility-wins","test":"return style('.badge.bg-accent', 'background-color') === 'rgb(253, 230, 138)';"},{"id":"component-kept","test":"const b = $$('.badge').find((el) => !el.classList.contains('bg-accent')); return style(b, 'background-color') === 'rgb(237, 233, 254)' && style(b, 'color') === 'rgb(91, 33, 182)';"},{"id":"uses-layers","test":"const all = []; const walk = (rules) => { for (const r of rules) { all.push(r); if (r.cssRules) walk(r.cssRules); } }; for (const s of document.styleSheets) walk(s.cssRules); return all.some((r) => r instanceof CSSLayerBlockRule);"},{"id":"selector-unchanged","test":"const all = []; const walk = (rules) => { for (const r of rules) { all.push(r); if (r.cssRules) walk(r.cssRules); } }; for (const s of document.styleSheets) walk(s.cssRules); return all.some((r) => r.selectorText === '.schedule .session-card .badge');"},{"id":"no-important","test":"return ![...document.querySelectorAll('style')].some((s) => s.textContent.includes('!important'));"}],"title":"دع الـ utility تفوز بالـ layers","prompt":"<p>يجب أن تكون شارة <strong>Sold out</strong> صفراء (<code dir=\"ltr\">#fde68a</code>) لأنها تحمل الـ utility <code dir=\"ltr\">.bg-accent</code>، لكن selector الـ component <code dir=\"ltr\">.schedule .session-card .badge</code> يتفوّق عليها في الدرجة. ضع القواعد في طبقات cascade (<code dir=\"ltr\">reset</code> و<code dir=\"ltr\">components</code> و<code dir=\"ltr\">utilities</code> بهذا الترتيب) لتفوز الـ utilities. أبقِ كل selector كما هو تمامًا ولا تستخدم <code dir=\"ltr\">!important</code>. ويجب أن تحتفظ شارة <strong>Layout</strong> العادية بنمط الـ component الخزامي (lavender).</p>\n","hints":["ابدأ ملف الأنماط بتعليمة واحدة تعلن أسماء الـ layers الثلاث بترتيب أولويتها.","غلّف كل مجموعة قواعد بـ <code dir=\"ltr\">@layer name { … }</code>. الترتيب داخل الملف لا يهم بعد أن تثبّته التعليمة.","<code dir=\"ltr\">@layer reset, components, utilities;</code> ثم <code dir=\"ltr\">@layer components { … }</code> و<code dir=\"ltr\">@layer utilities { .bg-accent { … } }</code>."],"explanation":"<p>تعليمة <code dir=\"ltr\">@layer reset, components, utilities;</code> تثبّت الترتيب، فيتغلّب أيّ تصريح عادي في <code dir=\"ltr\">utilities</code> على أيّ تصريح في <code dir=\"ltr\">components</code>، قبل مقارنة الـ specificity. يحتفظ selector الشارة بوزنه (0,3,0)، وهو وزن ما زال مهمًا داخل layer الـ components، لكنه لم يعد يتنافس مع الـ utility. ترك <code dir=\"ltr\">.bg-accent</code> خارج الـ layers سيجعلها تفوز أيضًا، لأن الأنماط خارج الـ layers تتغلّب على ما بداخلها، لكن تسمية الـ layer تُبقي النيّة واضحة لمن يأتي بعدك.</p>\n","checkLabels":{"utility-wins":"شارة Sold out صفراء","component-kept":"شارة Layout تحتفظ بنمط الـ component الخزامي","uses-layers":"الـ CSS تستخدم كتل @layer","selector-unchanged":"selector الـ component لم يتغيّر","no-important":"لا توجد !important في أيّ مكان من الـ CSS"}},"words":708,"readMinutes":4}