الدقة

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;
}

محدّد رقم التعريف

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

في المثال التالي، تكون درجة التحديد (1,0,0)

#myID {
  color: red;
}

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

تحتوي CSS على العديد من أدوات الاختيار. ولا يضيف بعضها أي تفاصيل. على سبيل المثال، لا يضيف الفئة الزائفة :not() أي قيمة إلى عملية احتساب التحديد.

يتم استبدال درجة التحديد الخاصة بالفئة الزائفة :not() بدرجة التحديد الخاصة بالمحدّد الأكثر تحديدًا في وسيطة المحدّدات المفصولة بفواصل، ما يوفّر درجة التحديد نفسها كما لو كانت مكتوبة :not(:is(argument)).

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

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

:is(h1, h2, h3) {
  color: blue;
}

تبلغ درجة التحديد في هذه العيّنة (0,0,1) لأنّها تتضمّن نوعًا واحدًا فقط من أدوات الاختيار (type).

مع إضافة id، تزداد الخصوصية إلى (1,0,0).

:is(h1, h2, h3, #my-heading) {
  color: blue;
}

تختلف الفئة الصورية :where(). وبغض النظر عن مدى تحديد أي من وسيطاتها، فإنّ لها دائمًا قيمة تحديد تبلغ (0,0,0).

:where(h1, h2, h3, #my-heading) {
  color: blue;
}

تتيح لك الأنماط ذات الخصوصية المنخفضة التي يتم تطبيقها باستخدام :where() إلغاء هذه الأنماط باستخدام أدوات اختيار أساسية في وقت لاحق في ورقة الأنماط:

:where(#my-content) {
   color: red;
}

p {
   color: blue;
}

على الرغم من أنّ :where() يتضمّن id في قائمة وسيطاته، إلا أنّه لا يزال يتضمّن قيمة تحديد (0, 0, 0) فقط، لذا فإنّ أداة الاختيار الأساسية p تلغيها وسيكون النص blue.

اختبِر معلوماتكَ

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

ما هي خصوصية a[href=/learn/css/%22#%22%5D%3C%2Fcode>؟

(0,0,1)
تبلغ قيمة a(0,0,1)، بينما تبلغ قيمة [href=/learn/css/%22#%22%5D%3C%2Fcode> ‏(0,1,0).
(0,1,0)
يُرجى إعادة المحاولة. تبلغ قيمة a(0,0,1)، بينما تبلغ قيمة [href=/learn/css/%22#%22%5D%3C%2Fcode> ‏(0,1,0).
(0,1,1)
تبلغ قيمة a(0,0,1) وتبلغ قيمة [href=/learn/css/%22#%22%5D%3C%2Fcode> ‏(0,1,0)، ما يجعل النوعية الإجمالية (0,1,1).

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

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

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

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

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

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

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

!important بيانات

لا تؤثّر علامة !important في نهاية تعريف CSS في درجة التحديد، ولكنّها تضع التعريف في مصدر مختلف، وهو Authored !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
تضيف العناصر تحديدًا يشبه العناصر (المكوّن `C`). يتضمّن أداة الاختيار عنصرَين، ما يجعل درجة التحديد (0,0,2).
article.card.dark
تضيف العناصر تحديدًا يشبه العناصر (المكوّن C)، وتضيف الفئات تحديدًا يشبه الفئات (المكوّن B). مع فئتَين وعنصر واحد، يصبح لهذا المحدّد درجة تحديد (0,2,1).
article:hover a[href]
تضيف العناصر تحديدًا يشبه العناصر (المكوّن `C`)، وتضيف الفئات الزائفة والسمات تحديدًا يشبه الفئات (المكوّن `B`). هناك محدِّدان للعناصر (2 × (0,0,1))، ومحدِّد سمات (بقيمة (0,1,0))، ومحدِّد فئات (بقيمة (0,1,0))، ما يجعل هذا المحدِّد يتمتّع بتحديد إجمالي يبلغ (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)

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

بالاستمرار في مثال الزرّ في الوقت الحالي، بدِّل CSS إلى ما يلي:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

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

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

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

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

الموارد