مراجعة سريعة
في درس المحدّدات المتقدمة تعلّمنا الجامعات والأصناف الزائفة. هذا الدرس يضيف ثلاثة محدّدات أحدث حلّت مشاكل حقيقية ظلّت عالقة لسنوات — وأصبحت مدعومة في كل المتصفحات الحديثة.
:is() — اختصار قائمة محدّدات طويلة
بدل تكرار نفس النسل لعدّة عناصر أب:
/* الطريقة القديمة */
header a:hover,
nav a:hover,
footer a:hover { color: #7c5cff; }
/* :is() تختصرها بسطر */
:is(header, nav, footer) a:hover { color: #7c5cff; }
نقطة مهمة في الأولوية (Specificity): :is() يأخذ أولوية أقوى وسيط بداخله. يعني :is(#id, .class) يُحسب بأولوية #id رغم أن .class موجودة أيضًا بالقائمة.
:where() — نفس الفكرة لكن بأولوية صفر
يعمل تمامًا مثل :is() في التجميع، لكنه لا يضيف أي أولوية مهما كان تعقيد ما بداخله:
:where(header, nav, footer) a { color: gray; } /* أولوية = 0 */
footer a { color: blue; } /* يتغلّب عليها بسهولة رغم بساطته */
🔑 استخدم
:where()عند كتابة أنماط أساسية (مكتبة مكوّنات، ثيم افتراضي) تريد أن يسهل على أي مطوّر آخر تجاوزها لاحقًا بمحدّد بسيط.
:has() — محدّد الأب الذي انتظرناه سنوات
لعقود، CSS لم يكن يستطيع تنسيق عنصر بناءً على أبنائه. :has() غيّر ذلك:
/* نسّق section فقط إذا كان بداخلها عنصر بصنف "featured" */
section:has(.featured) {
border: 2px solid #7c5cff;
}
/* h1 متبوع مباشرة بـ h2 → قلّل المسافة بينهما */
h1:has(+ h2) {
margin-bottom: 0.25rem;
}
/* بطاقة تحوي صورة معطوبة → أخفِ الحاوية */
.card:has(img[src=""]) {
display: none;
}
هذا يفتح استخدامات كانت تحتاج جافاسكريبت سابقًا:
/* نموذج فيه حقل غير صالح → لوّن الحاوية بالكامل */
.field:has(input:invalid) {
border-color: #ff4d4f;
}
/* تسمية checkbox عند تفعيله */
label:has(input:checked) {
background: #ede9fe;
font-weight: bold;
}
تنبيه أداء
:has() قوي لكنه يفحص الشجرة الفرعية لكل عنصر مرشّح، فتجنّب ربطه بعناصر واسعة جدًا:
/* ❌ يفحص كل الصفحة تقريبًا */
body:has(.modal-open) { overflow: hidden; }
/* ✅ نطاق أضيق ومحدّد */
.app-shell:has(.modal-open) { overflow: hidden; }
قائمة "متسامحة" — ميزة خفية
الثلاثة تشترك بخاصية عملية: إذا كتبت محدّدًا غير مدعوم داخل القائمة، لا تفشل القائمة كاملة (كما يحدث بالمحدّدات العادية المفصولة بفاصلة) — يُتجاهَل الجزء غير المدعوم فقط ويعمل الباقي.
جدول الفروقات
| المحدّد | يضيف أولوية؟ | الاستخدام الأساسي |
|---|---|---|
:is() | نعم (أقوى وسيط) | اختصار قوائم محدّدات |
:where() | لا (صفر دائمًا) | أنماط أساسية يسهل تجاوزها |
:has() | نعم (أقوى وسيط) | تنسيق عنصر حسب أبنائه/إخوته |
الأخطاء الشائعة
- ❌ توقّع أولوية صفر من
:is()→ فقط:where()تفعل ذلك. - ❌ ربط
:has()بعناصر جذرية عريضة (body,html,*) → بطء ملحوظ على صفحات كبيرة. - ❌ نسيان أن
:has()تدعم الجامعات بداخلها (:has(+ h2),:has(> img)) لا الأبناء فقط.
خلاصة
:is() و:where() يختصران قوائم المحدّدات الطويلة (الفرق بينهما: الأولوية)، و:has() أخيرًا يمنح CSS محدّد أب حقيقيًا — استخدمه بحذر مع نطاقات ضيقة لتفادي بطء الأداء.