:has()
محدّد الأب — has :has()
:has() يطابق عنصرًا بناءً على أبنائه أو إخوته التالين — أول محدّد أب حقيقي في تاريخ CSS.
لعقود لم تستطع CSS تنسيق عنصر بناءً على ما بداخله؛ الاتجاه كان دائمًا من الأب إلى الابن، لا العكس. :has() كسر هذه القاعدة: section:has(.featured) تختار section فقط إذا كانت تحوي عنصرًا بصنف featured، وh1:has(+ h2) تختار h1 فقط إذا تلاها h2 مباشرة.
هذا يفتح استخدامات كانت تحتاج جافاسكريبت سابقًا، مثل تلوين حاوية نموذج كاملة إذا كان أحد حقولها غير صالح (input:invalid)، أو تصميم تسمية checkbox بمجرّد تفعيله. لكن الأداء له ثمن: المتصفح يفحص الشجرة الفرعية عند كل تغيير DOM محتمل، لذا يُنصح بربطه بحاويات ضيقة بدل عناصر عريضة مثل body أو html.
الصياغة
section:has(.featured) { border: 2px solid #7c5cff; }
.field:has(input:invalid) { border-color: #ff4d4f; }
h1:has(+ h2) { margin-bottom: 0.25rem; }⚡ جرّب بنفسك
عدّل الكود واضغط «تحديث» لترى النتيجة فورًا — التجربة أفضل معلّم.
<style>
.card { border: 2px solid #e5e7eb; border-radius: 10px; padding: 12px; margin-bottom: 8px; }
.card:has(input:checked) { border-color: #7c5cff; background: #ede9fe; }
</style>
<label class="card"><input type="checkbox" checked /> بطاقة مفعّلة تتلوّن كاملة</label>
<label class="card"><input type="checkbox" /> بطاقة غير مفعّلة</label>أهم القيم
| القيمة | الوظيفة |
|---|---|
| :has(.child) | يطابق الأب إذا وُجد بداخله عنصر مطابق (نسل) |
| :has(> .child) | يطابق الأب إذا كان له ابن مباشر مطابق |
| :has(+ .sibling) | يطابق العنصر إذا تلاه شقيق مطابق مباشرة |
💡 نصائح عملية
- استخدمه بدل جافاسكريبت لحالات بسيطة مثل تلوين نموذج فيه حقل غير صالح
- قيّد نطاقه بحاوية محدّدة (.app-shell:has(...)) بدل body أو * لأداء أفضل
⚠️ أخطاء شائعة
- ربطه بعناصر جذرية عريضة (body, html, *) في صفحات كبيرة → بطء ملحوظ
- الظن أنه يعمل فقط مع الأبناء — يدعم أيضًا الجامعات + و~ لاختيار الإخوة
خصائص ذات صلة
🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار CSS الكامل بالعربي.
📚 للتعمق التقني الكامل بالإنجليزية: MDN Web Docs