تخطَّ إلى المحتوى

🟦 شرح CSS

محدّدات حديثة: :is() و:where() و:has()

الدرس 25 من 28· ⏱ 3 دقائق قراءة· 🗓 آخر تحديث: ٢١ يوليو ٢٠٢٦

مراجعة سريعة

في درس المحدّدات المتقدمة تعلّمنا الجامعات والأصناف الزائفة. هذا الدرس يضيف ثلاثة محدّدات أحدث حلّت مشاكل حقيقية ظلّت عالقة لسنوات — وأصبحت مدعومة في كل المتصفحات الحديثة.

: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 محدّد أب حقيقيًا — استخدمه بحذر مع نطاقات ضيقة لتفادي بطء الأداء.

شرح محدّدات حديثة: :is() و:where() و:has() — CSS بالعربي
محدّدات حديثة: :is() و:where() و:has()CSS بالعربي · The Code Fix

📚 لمزيد من التعمّق في CSS، راجِع توثيق CSS على MDN.

هل كان هذا الدرس مفيدًا؟