{"id":"l-css-1-1","courseId":"css-mastery","lang":"ar","kind":"intro","summary":"اشرح الترتيب الذي يحسم به المتصفّح التصريحات المتنافسة، لتتوقّع القاعدة الفائزة قبل أن تفتح DevTools.","html":"<p>كل خطأ في CSS يجعلك تقول «لكنني <em>كتبت</em> هذه القاعدة!» له السبب الجذري نفسه: أكثر من تصريح (declaration) أراد الخاصية نفسها على العنصر نفسه، فاختار المتصفّح غير الذي اخترته أنت. المتصفّح لا يتصرّف عشوائيًا؛ إنه ينفّذ خوارزمية ترتيب ثابتة اسمها <strong>الـ cascade</strong> (التتالي)، وحين تستطيع تشغيلها في رأسك تتوقّف CSS عن أن تبدو لعبة «اضرب الخُلد» التي لا تنتهي.</p>\n<p>هذه الدورة تعلّمك CSS من جهة المتصفّح. ستتعلّم ما تفعله كل ميزة حديثة، وستتعلّم أيضًا <em>لماذا يتصرّف المتصفّح بهذه الطريقة</em>، لأن هذا بالضبط ما يتيح لك توقّع النتيجة قبل أن تعيد تحميل الصفحة.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">الصفحة التي ستبنيها</h2>\n<p>على طول الدورة ستحسّن صفحة حقيقية واحدة: جدول <strong>Waypoint Conf 2026</strong>، وهو مؤتمر للواجهات الأمامية يمتد يومين. فيها رأس صفحة ثابت (sticky)، وشريط فلاتر بمربّعات اختيار للمسارات، وبطاقات للجلسات (الوقت والعنوان والمتحدّث والقاعة وشارة المسار)، وشبكة للمتحدّثين بصورهم، ووضع داكن. تبدأ الصفحة بـ CSS بسيطة ومكسورة قليلًا، وفي النهاية تستخدم الـ layers والـ container queries وألوان <code dir=\"ltr\">oklch()</code> والـ view transitions ومعمارية يستطيع فريق من خمسة أشخاص أن يتشاركها.</p>\n<p>هذا أول تعارض ستقابله فيها:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"html\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">HTML</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:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> class</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"session\"</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> id</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"keynote\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> class</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"session-title\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Keynote: The Platform Is the Framework&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span></code></pre></div>\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:#0550AE;--shiki-dark:#79C0FF\">#keynote</span><span style=\"color:#116329;--shiki-dark:#7EE787\"> h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">color</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">#6d28d9</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; }</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.session</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> .session-title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">color</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">#1f2937</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; }</span></span></code></pre></div>\n<p>القاعدة الثانية تأتي لاحقًا، لذا يتوقّع كثيرون أن يكون العنوان رماديًا داكنًا. لكنه بنفسجي. ولتفهم السبب تحتاج إلى معرفة ترتيب الفرز.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">الـ cascade خطوة بخطوة</h2>\n<p>حين تستهدف عدّة تصريحات الخاصية نفسها على العنصر نفسه، يرتّبها المتصفّح وفق المعايير التالية بالترتيب، ويتوقّف عند أول معيار يفرّق بينها:</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 300\" role=\"img\" aria-labelledby=\"l-css-1-1-t1\"><defs><marker id=\"arrow-l-css-1-1-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-1-t1\">خمس خطوات متراصّة: المصدر والأهمية، النمط المضمّن، طبقات الـ cascade، الـ specificity، ترتيب الظهور. يمرّ سهم نزولًا عبرها، وأول خطوة تفرّق بين تصريحين تحسم الفائز.</title>\n  <rect class=\"d-box-primary\" x=\"40\" y=\"16\" width=\"420\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"60\" y=\"44\">1. المصدر والأهمية</text>\n  <rect class=\"d-box\" x=\"40\" y=\"72\" width=\"420\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"60\" y=\"100\">2. السمة style المضمّنة</text>\n  <rect class=\"d-box\" x=\"40\" y=\"128\" width=\"420\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"60\" y=\"156\">3. طبقات الـ cascade (@layer)</text>\n  <rect class=\"d-box\" x=\"40\" y=\"184\" width=\"420\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"60\" y=\"212\">4. الـ Specificity</text>\n  <rect class=\"d-box\" x=\"40\" y=\"240\" width=\"420\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"60\" y=\"268\">5. ترتيب الظهور</text>\n  <path class=\"d-arrow\" d=\"M500 30 L500 270\" marker-end=\"url(#arrow-l-css-1-1-1)\"/>\n  <text class=\"d-label-muted\" x=\"520\" y=\"140\">تعادل؟ انزل</text>\n  <text class=\"d-label-muted\" x=\"520\" y=\"162\">خطوة</text>\n</svg><figcaption>يقارن الـ cascade التصريحات معيارًا بعد معيار ويتوقّف عند أول اختلاف</figcaption></figure>\n<ol>\n<li><strong>المصدر والأهمية.</strong> تأتي التصريحات من ملف الأنماط الافتراضي في المتصفّح (user-agent)، أو من المستخدم (إعدادات إمكانية الوصول والإضافات)، أو منك أنت (author). قواعدك العادية تتغلّب على افتراضيات المتصفّح. و<code dir=\"ltr\">!important</code> تقلب الترتيب، فتتغلّب قاعدة المستخدم المهمّة على قاعدتك. وهذا مقصود: من يحتاج إلى نص كبير يجب أن يستطيع تجاوز تصميمك.</li>\n<li><strong>الأنماط المضمّنة.</strong> السمة <code dir=\"ltr\">style=&quot;…&quot;</code> على العنصر تتغلّب على أيّ selector في ملف الأنماط. (في المواصفة خطوة أخرى قبل هذه مباشرةً تخصّ عزل الـ Shadow DOM، ولا تهمّك إلا حين تبني web components.)</li>\n<li><strong>طبقات الـ cascade.</strong> القواعد في الـ <code dir=\"ltr\">@layer</code> المُعلَنة لاحقًا تتغلّب على القواعد في الطبقات الأسبق، بغضّ النظر عن الـ specificity. ستستخدم هذا في درس <a href=\"/ar/lesson/css-mastery/l-css-1-3\">طبقات الـ Cascade باستخدام @layer</a>.</li>\n<li><strong>الـ Specificity</strong> (درجة التحديد). مدى دقّة الـ selector في استهداف العنصر. الـ IDs تتغلّب على الـ classes، والـ classes تتغلّب على أنواع العناصر.</li>\n<li><strong>ترتيب الظهور.</strong> إن تعادل كل ما سبق، يفوز التصريح الذي يظهر أخيرًا.</li>\n</ol>\n<p>لنعد إلى الـ keynote: كلتا القاعدتين من أنماطك العادية، ولا إحداهما مضمّنة، ولا إحداهما داخل layer. إذن الخطوة 4 هي التي تحسم. <code dir=\"ltr\">#keynote h2</code> يحتوي على ID، و<code dir=\"ltr\">.session .session-title</code> لا يحتوي إلا على classes، وID واحد يتفوّق على أيّ عدد من الـ classes. البنفسجي يفوز، والترتيب لا يُستشار أصلًا.</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>البدء بترتيب الظهور</span></p>\n<p>«انقل القاعدة إلى الأسفل» هو أشهر إصلاح في CSS، ولا ينجح إلا حين تكون الـ specificity متعادلة أصلًا. إن كانت القاعدة التي نقلتها أقل specificity فستخسر رغم ذلك. افحص الـ specificity قبل أن تنقل أيّ شيء.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">حين لا يفوز أحد</h2>\n<p>أحيانًا لا يستهدف أيّ تصريح خاصيةً ما على الإطلاق. لكن المتصفّح يحتاج إلى قيمة رغم ذلك، فيلجأ إلى الافتراضي: <strong>الخصائص الموروثة</strong> مثل <code dir=\"ltr\">color</code> و<code dir=\"ltr\">font-family</code> و<code dir=\"ltr\">line-height</code> تنسخ قيمة العنصر الأب، و<strong>الخصائص غير الموروثة</strong> مثل <code dir=\"ltr\">border</code> و<code dir=\"ltr\">padding</code> و<code dir=\"ltr\">background-color</code> تأخذ قيمتها الابتدائية. لهذا فإن ضبط <code dir=\"ltr\">font-family</code> على <code dir=\"ltr\">body</code> ينسّق الصفحة كلها، بينما ضبط <code dir=\"ltr\">padding</code> على <code dir=\"ltr\">body</code> يضيف حشوة إلى الـ body وحده.</p>\n<aside class=\"callout callout-tip\" 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=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>دع DevTools تُريك الـ cascade</span></p>\n<p>في Chrome أو Firefox، افحص العنصر وافتح لوحة Styles. التصريحات الخاسرة يظهر عليها خط يشطبها، وتبويب Computed يبيّن أيّ قاعدة زوّدت كل قيمة نهائية. استخدمها لتتأكّد من التوقّع الذي بنيته في رأسك.</p>\n</aside>\n<p>الدرس التالي يفكّك الخطوة 4: كيف تُحسب الـ specificity، ولماذا يستطيع ID واحد أن يخرّب مكتبة components كاملة، وكيف يتيح لك <code dir=\"ltr\">:is()</code> و<code dir=\"ltr\">:where()</code> أن تختار بدقّة الوزن الذي يحمله الـ selector.</p>\n","toc":[{"id":"sec-1","text":"الصفحة التي ستبنيها","level":2},{"id":"sec-2","text":"الـ cascade خطوة بخطوة","level":2},{"id":"sec-3","text":"حين لا يفوز أحد","level":2}],"takeaways":["يرتّب الـ cascade التصريحات المتنافسة حسب المصدر والأهمية، ثم الأنماط المضمّنة (inline)، ثم الـ layers، ثم الـ specificity، وبعد ذلك فقط حسب ترتيب الظهور في الكود.","ترتيب الظهور هو آخر وسيلة لكسر التعادل لا أوّلها، لذا فإن نقل القاعدة إلى أسفل الملف يصلح أخطاء أقل بكثير مما يتوقّعه الناس.","حين لا يستهدف أيّ تصريح خاصيةً ما، يلجأ المتصفّح إلى الوراثة في الخصائص الموروثة، وإلى القيمة الابتدائية في بقية الخصائص.","<code dir=\"ltr\">!important</code> تعكس ترتيب المصادر: قاعدة المستخدم المهمّة تتغلّب على قاعدة المطوّر المهمّة."],"further":[{"title":"Introduction to the CSS cascade (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascade/Introduction"},{"title":"The cascade (web.dev Learn CSS)","url":"https://web.dev/learn/css/the-cascade"}],"quiz":[{"q":"<p>قاعدتان في ملف الأنماط نفسه تستهدفان العنصر <code dir=\"ltr\">&lt;h2 class=&quot;session-title&quot;&gt;</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:#0550AE;--shiki-dark:#79C0FF\">.session-title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">color</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">teal</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; }</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">color</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">crimson</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">; }</span></span></code></pre></div>\n","options":[{"text":"crimson، لأنها تأتي لاحقًا في الملف.","why":"ترتيب الظهور يكسر التعادل فقط بين تصريحات لها الـ specificity نفسها. والـ class يتغلّب على selector النوع قبل أن يُنظر إلى الترتيب أصلًا."},{"text":"teal، لأن selector الـ class أدقّ تحديدًا من selector النوع.","why":"صحيح. الـ specificity (0,1,0) تتغلّب على (0,0,1)، والـ specificity تُفحص قبل ترتيب الظهور."},{"text":"أيًّا كان اللون الذي يحدّده ملف الأنماط الافتراضي في المتصفّح لـ h2.","why":"ملف أنماط المتصفّح (user-agent) مصدر أقل أولوية من أنماطك أنت، لذا لا تتغلّب تصريحاته العادية أبدًا على قاعدة كتبتها."}],"answer":1},{"q":"<p>فقرة داخل <code dir=\"ltr\">.card</code> ليس لها قاعدة <code dir=\"ltr\">color</code> خاصة بها، و<code dir=\"ltr\">.card</code> تضبط <code dir=\"ltr\">color: navy</code>. ما اللون الذي تأخذه الفقرة؟</p>","options":[{"text":"القيمة الابتدائية لـ <code dir=\"ltr\">color</code>، وهي عادةً الأسود.","why":"هذا ما يحدث في الخصائص غير الموروثة. أما <code dir=\"ltr\">color</code> فخاصية موروثة، لذا تأخذ الفقرة القيمة المحسوبة لعنصرها الأب."},{"text":"لا شيء؛ تبقى الخاصية بلا قيمة حتى تستهدفها قاعدة ما.","why":"لكل عنصر قيمة لكل خاصية. وحين لا تستهدفها أيّ قاعدة، يملأها المتصفّح بالوراثة أو بالقيمة الابتدائية."},{"text":"navy، لأن <code dir=\"ltr\">color</code> خاصية موروثة.","why":"صحيح. في غياب قيمة من الـ cascade، تنسخ الخصائص الموروثة القيمة المحسوبة للعنصر الأب."}],"answer":2},{"q":"<p>ما الخطوة التي يفحصها المتصفّح أولًا حين يتنافس تصريحان؟</p>","options":[{"text":"المصدر والأهمية.","why":"صحيح. كون التصريح من المتصفّح أو من المستخدم أو منك، وكونه <code dir=\"ltr\">!important</code> أو لا، يُحسم قبل الـ layers والـ specificity."},{"text":"الـ specificity.","why":"الـ specificity لا تقارن إلا تصريحات متعادلة أصلًا في المصدر والأهمية والنمط المضمّن والـ layer."},{"text":"ترتيب الظهور.","why":"الترتيب هو آخر ما يكسر التعادل، ولا يُستخدم إلا حين يتساوى كل شيء آخر."},{"text":"طبقات الـ cascade.","why":"الـ layers تأتي بعد المصدر والأهمية والأنماط المضمّنة في عملية الترتيب."}],"answer":0}],"exercise":null,"words":604,"readMinutes":4}