الدقة

The CSS Podcast - 003: Specificity

لنفترض أنّك تعمل مع رمز HTML وCSS التاليَين:

<button class="branding">Hello, Specificity!</button>
.branding {
  color: blue;
}

button {
  color: red;
}

هناك قاعدتان تستهدفان العنصر نفسه هنا. تحتوي كل قاعدة على بيان يريد ضبط لون الزر: يحاول أحدهما تلوين الزر باللون الأحمر ويحاول الآخر تلوين الزر باللون الأزرق. ما هو البيان الذي يتم تطبيقه على العنصر؟

إنّ فهم خوارزمية تحديد CSS هو المفتاح لفهم كيفية اختيار CSS بين العناصر المتنافسة.

إنّ التحديد هو إحدى المراحل المميزة للسلسلة، وقد تم تناوله في الوحدة الأخيرة حول السلسلة.

تسجيل نتيجة الدقة

تحصل كل قاعدة أداة اختيار ضمن مصدر على تقييم. يمكنك اعتبار النوعية كنتيجة إجمالية ويحصل كلّ نوع من أنواع المحدّدات على نقاط نحو تلك النتيجة. يتم اختيار البيانات من القواعد الأكثر تحديدًا.

في مشروع حقيقي، يتمثل التوازن في التأكّد من تطبيق قواعد CSS التي تتوقّع تطبيقها، مع الحفاظ على انخفاض الدرجات بشكل عام لتجنّب التعقيد. يجب أن تكون الدقة عالية بما يكفي فقط، بدلاً من السعي إلى تحقيق أعلى دقة ممكنة. في المستقبل، قد يكون من الضروري تطبيق بعض قواعد CSS الأكثر أهمية. إذا كنت تسعى إلى تحقيق أعلى درجة من التحديد، ستصعِّب هذه المهمة.

الدقة ليست عددًا عشريًا بل ثلاثية تتكون من ثلاثة مكوّنات: A وB وC.

  • A: دقة تشبه دقة المعرّف
  • B: دقة شبيهة بالفئة
  • C: تحديد العناصر

ويتم تمثيله غالبًا باستخدام الرمز (A,B,C). على سبيل المثال: (1,0,2). ويُستخدَم أيضًا الرمز البديل A-B-C بشكل شائع.

رسم بياني يعرض المكوّنات الثلاثة للتحديد (أ، ب، ج) يعرِض المخطّط البياني لكل مكوّن ما يمثّله وبعض أمثلة على المحدّدات التي تؤثّر فيه.
رسم بياني يوضّح مكوّن التحديد الذي تؤثر فيه أدوات الاختيار المختلفة

مقارنة الخصائص

تتم مقارنة التحديدات من خلال مقارنة المكوّنات الثلاثة بالترتيب: تكون التحديد التي تتضمن قيمة أكبر من A أكثر تحديدًا. إذا كانت قيمتَا A متساويتين، تكون التحديد التي تتضمن قيمة أكبر من B أكثر تحديدًا. إذا كانت قيمتَا B متساويتين أيضًا، تكون التحديد التي تتضمن قيمة أكبر من C أكثر تحديدًا. إذا كانت جميع القيم متساوية، تكون التحديدتان متساويتين.

على سبيل المثال، يُعتبر (1,0,0) أكثر دقة من (0,4,3) لأنّ قيمة A في (1,0,0) (وهي 1) أكبر من قيمة A من (0,4,3) (وهي 0).

تؤثر أدوات الاختيار في مدى التحديد.

يبدأ كل جزء في الثلاثية الخاصة بالتحديد بقيمة 0، وتكون القيمة التلقائية للتحديد هي (0,0,0). يزيد كل جزء من أداة الاختيار من التحديد الذي يؤدي، استنادًا إلى نوع أداة الاختيار، إلى زيادة قيمة A أو B أو C.

أداة اختيار جميع أنواع العناصر

لا يضيف المُحدِّد الشامل (*) أي تحديد، ويترك قيمته على التحديد الأولي (0,0,0).

* {
  color: red;
}

محدِّد العنصر أو العنصر النائب

يضيف محدد العنصر (النوع) أو العنصر الاصطناعي تحديدًا يشبه العنصر، ما يزيد المكوّن C بمقدار 1.

تبلغ القيمة الإجمالية لمعيار التحديد في الأمثلة التالية (0,0,1).

أداة اختيار النوع

div {
  color: red;
}

أداة اختيار العناصر الزائفة

::selection {
  color: red;
}

أداة اختيار فئة أو فئة زائفة أو سمة

تضيف أداة اختيار الفئة أو الفئة الزائفة أو السمة تحديدًا شبيهًا بالفئة يزيد من مكوّن B بمقدار 1.

تبلغ نسبة النوعية في الأمثلة التالية (0,1,0).

أداة اختيار الفئة

.my-class {
  color: red;
}

أداة اختيار الفئة الزائفة

:hover {
  color: red;
}

أداة اختيار السمات

[href='#'] {
  color: red;
}

أداة اختيار أرقام التعريف

يضيف محدِّد رقم التعريف تحديدًا مشابهًا لرقم التعريف، ما يزيد مكوّن C بمقدار 1، ما دام يتم استخدام محدِّد رقم تعريف (#myID) وليس محدِّد سمة ([id="myID"]).

في المثال التالي، تكون الدقّة (1,0,0).

#myID {
  color: red;
}

أدوات الاختيار الأخرى

تحتوي لغة CSS على العديد من أدوات الاختيار. ولا تضيف بعض هذه الكلمات مزيدًا من التحديد. على سبيل المثال، لا تضيف الفئة الزائفة :not() أيّ شيء إلى عملية احتساب النوعية.

ومع ذلك، تتم إضافة المحدّدات التي تم تمريرها كوسيطات إلى عملية احتساب النوعية.

div:not(.my-class) {
  color: red;
}

يحتوي هذا العيّنة على نسبة تمييز (0,1,1) لأنّه يحتوي على محدد نوع واحد (div) وفئة واحدة داخل :not().

التحقّق من فهمك

اختبِر معلوماتك حول احتساب درجة النوعية

ما هي سمة a[href="#"]؟

(0,0,1)
قيمة a هي (0,0,1)، ولكن قيمة [href="#"] هي (0,1,0).
(0,1,0)
يُرجى إعادة المحاولة. قيمة a هي (0,0,1)، ولكن قيمة [href="#"] هي (0,1,0).
(0,1,1)
قيمة a هي (0,0,1) وقيمة [href="#"] هي (0,1,1)، ما يجعل النوعية الإجمالية هي (0,1,1).

العوامل التي لا تؤثّر في النوعية

هناك بعض المفاهيم الخاطئة الشائعة حول العوامل التالية التي تؤثّر في التحديد.

سمات النمط المضمّنة

لا يؤثّر ملف CSS الذي يتم تطبيقه مباشرةً على سمة style لعنصر ما، في النوعية لأنّه خطوة مختلفة في التسلسل يتم تقييمها قبل النوعية.

<div style="color: red"></div>

لإلغاء هذا البيان من داخل جدول أسلوب، عليك اللجوء إلى الحصول على بيان الفوز في خطوة سابقة من التسلسل.

على سبيل المثال، يمكنك إضافة !important إليه، لكي يصبح جزءًا من مصدر !important الذي تم إنشاؤه.

!important بيان

لا يؤثّر الرمز !important في نهاية تعريف CSS على النوع المميّز ولكنّه يضع التعريف في مصدر مختلف، وهو !important من تأليف.

في المثال التالي، لا تكون التحديد الخاص بـ .my-class ذا صلة بفوز بيان !important.

.my-class {
  color: red !important;
  color: white;
}

عندما يكون !important لكل بيانَين، تُستخدَم السمة المحدّدة مرة أخرى، لأنّ خطوة المصدر من التسلسل الهرمي لم تتمكّن من تحديد الفائز بعد.

.branding {
  color: blue !important;
}

button {
  color: red !important;
}

النوعية في السياق

عند استخدام أداة اختيار معقّدة أو مركبة، يساهم كل جزء من هذه الأداة في زيادة التحديد. إليك مثال على رمز HTML:

<a class="my-class another-class" href="#">A link</a>

يتضمّن هذا الرابط صفَّين دراسيَّين. تحتوي القاعدة في ملف CSS التالي على درجة تحديد (0,0,1):

a {
  color: red;
}

إذا كنت تشير إلى إحدى الفئات في أداة الاختيار، سيكون لها الآن درجة دقة تبلغ (0,1,1):

a.my-class {
  color: green;
}

أضِف الفئة الأخرى إلى أداة الاختيار، وأصبح لديها الآن درجة خصوصية تبلغ (0,2,1):

a.my-class.another-class {
  color: rebeccapurple;
}

أضِف السمة href إلى أداة الاختيار، وأصبح لديها الآن درجة دقة تبلغ (0,3,1):

a.my-class.another-class[href] {
  color: goldenrod;
}

أخيرًا، أضِف فئة زائفة :hover إلى كل ذلك، وينتهي أداة الاختيار بنسبة تحديد (0,4,1):

a.my-class.another-class[href]:hover {
  color: lightgrey;
}

التحقّق من فهمك

اختبِر معلوماتك حول احتساب درجة النوعية

أيّ من أدوات الاختيار التالية لها خصوصية (0,2,1)؟

article > section
تضيف العناصر دقة شبيهة بالعنصر (المكوّن "ج"). هناك عنصران في أداة الاختيار، ما يجعل هذا العنصر محددًا بنسبة (0,0,2).
article.card.dark
تضيف العناصر دقة شبيهة بالعنصر (المكوّن "ج")، وتضيف الفئات دقة شبيهة بالفئة (المكوّن "ب"). مع فئتَين وعنصر واحد، يحصل هذا المحدّد على نسبة تمييز تبلغ (0,2,1).
article:hover a[href]
تضيف العناصر تحديدًا يشبه العنصر (المكوّن "ج")، وتضيف الفئات الزائفة والسمات تحديدًا يشبه الفئة (المكوّن "ب"). هناك محدِّدَان للعناصر ((0,0,1) × 2) ومحدِّد سمة (قيمة (0,0,1)) ومحدِّد فئة (قيمة (0,0,1)). يمنح ذلك هذا المحدِّد دقة إجمالية تبلغ (0,2,2).

زيادة النوعية بشكل عملي

لنفترض أنّ لديك بعض تنسيقات CSS التي تبدو على النحو التالي:

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

باستخدام رمز HTML الذي يبدو على النحو التالي:

<button class="my-button" onclick="alert('hello')">Click me</button>

يحتوي الزر على خلفية رمادية، لأنّ المحدّد الثاني له درجة تحديد (0,1,1). ويعود السبب في ذلك إلى أنّها تحتوي على أداة اختيار نوع واحدة (button)، وهي (0,0,1) وأداة اختيار سمة واحدة ([onclick])، وهي (0,1,0).

تساوي القاعدة السابقة .my-button (0,1,0) لأنّها تحتوي على أداة اختيار فئة واحدة، وهي أقل تحديدًا من (0,1,1).

إذا أردت تحسين هذه القاعدة، يمكنك تكرار أداة اختيار الفئة على النحو التالي:

.my-button.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

سيظهر الزر الآن بخلفية زرقاء، لأنّ أداة الاختيار الجديدة تحصل على درجة تحديد (0,2,0).

في حال تساوي درجة التحديد، يتم الرجوع إلى الخطوة التالية في التسلسل.

لنبقى في مثال الزرّ الآن ولنبدِّل خدمة مقارنة الأسعار إلى ما يلي:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

يحتوي الزر على خلفية رمادية، لأنّ كلتا أداتَي الاختيار تتضمّنان درجة تحديد متطابقة تبلغ (0,1,0).

في حال تبديل القواعد بترتيب المصدر، سيظهر الزر باللون الأزرق.

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

ويعود السبب في ذلك إلى أنّ كلا أداتَي الاختيار تتضمّنان التحديد نفسه. في هذه الحالة، يعود التسلسل إلى خطوة ترتيب الظهور.

الموارد