مقدمه
یکی از قدیمیترین درخواستهای جامعه توسعهدهندگان وب این بود:
«چرا نمیتوانیم والد یک عنصر را در CSS انتخاب کنیم؟»
قبل از :has()، اگر میخواستید بر اساس وضعیت یک فرزند، والدش را استایل دهید، مجبور بودید:
- از JavaScript استفاده کنید
- کلاس اضافه کنید
- یا ساختار HTML را تغییر دهید
اما حالا با معرفی شبهکلاس :has()، این محدودیت تاریخی بالاخره برطرف شده است.
:has() دقیقاً چیست؟
:has() یک شبهکلاس رابطهای (Relational Pseudo-class) است که به شما اجازه میدهد عنصری را انتخاب کنید اگر درون آن (یا در رابطه مشخصی با آن) المنتی خاص وجود داشته باشد.
ساختار کلی:
selector:has(relative-selector) {
/* styles */
}
به زبان ساده:
«این عنصر را انتخاب کن اگر داخلش این المنت وجود دارد.»
سادهترین مثال
انتخاب تمام div هایی که شامل یک img هستند:
div:has(img) {
border: 2px solid green;
}
هر div که حداقل یک تصویر داشته باشد، حاشیه سبز میگیرد.
چرا این ویژگی مهم است؟
چون برای اولین بار در CSS میتوانیم:
✅ والد را بر اساس فرزند انتخاب کنیم
✅ رفتارهای شرطی بسازیم
✅ بدون JS تعاملات پیچیده ایجاد کنیم
✅ UIهای هوشمندتر طراحی کنیم
کاربردهای عملی و حرفهای
۱. فرمهای هوشمند بدون JavaScript
استایل دادن به فیلد نامعتبر
.form-group:has(input:invalid) {
border: 2px solid red;
background-color: #fff5f5;
}
اگر ورودی داخل .form-group نامعتبر باشد، کل گروه قرمز میشود.
فعال شدن دکمه هنگام تیک خوردن چکباکس
.form:has(input[type="checkbox"]:checked) button {
background-color: green;
}
۲. کارتهای پویا بر اساس محتوا
کارت دارای تصویر
.card:has(img) {
padding-top: 0;
}
کارت دارای ویدیو
.card:has(video) {
border: 2px dashed red;
}
۳. منوهای تعاملی
وقتی آیتمی hover شده، کل منو تغییر کند
.menu:has(li:hover) {
background: #f5f5f5;
}
۴. گالری هوشمند
اگر فقط یک تصویر وجود دارد:
.gallery:has(.image:only-child) {
display: flex;
justify-content: center;
}
اگر چند تصویر وجود دارد:
.gallery:has(.image:nth-child(2)) {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
۵. تم تاریک بدون JavaScript
body:has(.theme-toggle:checked) {
background: #121212;
color: white;
}
یک چکباکس ساده میتواند کل تم سایت را تغییر دهد.
ترکیب با سایر شبهکلاسها
قدرت واقعی :has() زمانی مشخص میشود که با سایر selectorها ترکیب شود:
:not():is():where():nth-child():focus:checked:invalid:placeholder-shown
مثال پیشرفته:
.card:has(input:focus):not(:has(input:invalid)) {
box-shadow: 0 0 10px green;
}
مقایسه با روشهای قدیمی
قبل از :has():
const input = document.querySelector("input");
input.addEventListener("input", () => {
if (input.validity.valid) {
input.parentElement.classList.add("valid");
}
});
الان فقط با CSS:
.parent:has(input:valid) {
border: 2px solid green;
}
✅ کد کمتر
✅ سریعتر
✅ تمیزتر
✅ بدون JS
عملکرد (Performance)
از آنجا که :has() یک selector پیشرفته است، ممکن است در ساختارهای بسیار بزرگ DOM هزینه محاسباتی داشته باشد.
نکات بهینهسازی:
- از selectorهای بسیار عمیق داخل
:has()پرهیز کنید - آن را به سطح خاصی محدود کنید
- از کلاسهای مشخص استفاده کنید
مثال بهتر:
content_copy
cssnote_addویرایش با Canvas
.card:has(> img)
بهجای:
content_copy
cssnote_addویرایش با Canvas
body main section div.card:has(div.wrapper img)
پشتیبانی مرورگرها (۲۰۲۶)
در حال حاضر:
- ✅ Chrome / Edge → پشتیبانی کامل
- ✅ Safari → پشتیبانی کامل
- ✅ Firefox → پشتیبانی کامل
- ✅ مرورگرهای موبایل مدرن → پشتیبانی دارند
در سال ۲۰۲۶ تقریباً میتوان با خیال راحت از :has() در پروژههای production استفاده کرد.
محدودیتها
- نمیتواند اجداد بالاتر را انتخاب کند مگر از طریق همان عنصر هدف
- استفاده بیش از حد ممکن است پیچیدگی selector را بالا ببرد
- در CSS قدیمیتر (قبل از ۲۰۲۳) پشتیبانی نمیشود
جمعبندی
:has() یکی از بزرگترین پیشرفتهای CSS در دهه اخیر است.
این قابلیت:
- انتخابگر والد را ممکن کرد
- وابستگی به JavaScript را کاهش داد
- طراحی شرطی و هوشمند را سادهتر کرد
- معماری CSS را مدرنتر کرد
اگر هنوز از آن استفاده نمیکنید، حالا بهترین زمان است.
CSS دیگر فقط برای استایل نیست —
بلکه حالا میتواند رفتارهای شرطی پیچیده را هم مدیریت کند.
هنوز دیدگاهی ثبت نشده
اولین نفری باشید که نظر میدهد!