במשך שנים, ל-CSS לא הייתה דרך לבחור אלמנט הורה לפי מה שנמצא בתוכו. אם div הכיל תמונה, לא הייתה אפשרות לעצב אותו אחרת – לא בלי JavaScript. הפסאודו-קלאס :has, שהוצג ב-CSS Selectors Level 4, משנה את זה לחלוטין.
מהו מאפיין has:?
:has הוא פסאודו-קלאס יחסי שמטרגט אלמנט כאשר הצאצאים (או האחים) שלו עומדים בתנאי מסוים. אפשר לחשוב על זה כשאלה: "האם האלמנט הזה מכיל X?" – ישירות ב-CSS.
תחביר – Syntax
element:has(selector) {
/* styles */
}כאן, element הוא האלמנט שרוצים לעצב, ו-selector מתאר מה צריך להימצא בתוכו. ניתן גם להשתמש בקומבינטורים: element:has(> selector) מגביל את הבדיקה לצאצאים ישירים בלבד.
דוגמאות מעשיות
להלן מספר דפוסים נפוצים. כל אחד כולל את הקוד הסטטי וגם דמו אינטראקטיבי.
דוגמה 1: הדגשת אלמנט אב בהתבסס על Child Element
עיצוב div כשהוא מכיל אלמנט מסוג img:
<div>
<p>This div contains an image.</p>
<img src="https://via.placeholder.com/150" alt="Placeholder Image">
</div>
<div>
<p>This div does not contain an image.</p>
</div>div:has(img) {
border: 2px solid green;
padding: 10px;
}לחצו על הכפתור בדמו למטה כדי להוסיף או להסיר תמונה מהתיבה ולראות את הגבול משתנה בזמן אמת:
This box can contain an image.
This box never has an image. No green border.
דוגמה 2: עיצוב אלמנט הורה של פריט רשימה בהתבסס על אלמנט ילד
טרגוט ul כשהוא מכיל li עם מחלקה ספציפית:
<ul>
<li>Item 1</li>
<li class="highlight">Item 2</li>
<li>Item 3</li>
</ul>
<ul>
<li>Item A</li>
<li>Item B</li>
<li>Item C</li>
</ul>ul:has(li.highlight) {
background-color: lightyellow;
padding: 10px;
}דוגמה 3: עיצוב אימות טפסים
עיצוב מכולה של שדה טופס לפי מצב התקינות של ה-input – ללא צורך ב-JavaScript:
<form>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" required>
</div>
<button type="submit">Submit</button>
</form>.form-group:has(input:invalid) {
border: 2px solid red;
padding: 10px;
}הקלידו בשדה למטה וצפו בגבול מגיב בזמן אמת. הסלקטורים :has(input:invalid) ו-:has(input:valid) מטפלים במשוב החזותי:
CSS rule: .ch-form-group:has(input:valid) { border-color: #2d8a4e; }
שימושים מעשיים בסביבת ייצור
הדוגמאות הבסיסיות למעלה מראות כיצד :has() עובד. אבל הערך האמיתי מתגלה בדפוסים מעשיים שבעבר דרשו JavaScript.
Dark Mode Toggle עם has(:checked):
Checkbox בודד יכול לשלוט בסכמת הצבעים של רכיב שלם. המכולה משתמשת ב-:has(#darkmode:checked) כדי לעבור בין עיצוב בהיר לכהה. אפס שורות של JavaScript.
.card:has(#darkmode:checked) {
background: #0e1219;
color: #f1eeee;
}
.card:has(#darkmode:checked) .btn {
background: #FFB42F;
color: #0e1219;
}הפעילו את המתג למטה כדי לראות את זה בפעולה:
זיהוי מצב ריק – Empty State Detection
הצגת הודעת placeholder כשמכולה ריקה מפריטים. שילוב :has() עם :empty או פסאודו-קלאס של שלילה:
.list-container:not(:has(li)) .empty-state {
display: block;
}
.list-container:has(li) .empty-state {
display: none;
}בעבר היה צורך ב-JavaScript כמו if (list.children.length === 0). עכשיו הדפדפן מטפל בנראות באופן ריאקטיבי.
שאילתות כמות – Quantity Queries
עיצוב grid בצורה שונה לפי מספר הפריטים. אם יש 4 ילדים או יותר, מעבר למתווה רב-עמודות:
.grid:has(:nth-child(4)) {
grid-template-columns: repeat(2, 1fr);
}
.grid:not(:has(:nth-child(4))) {
grid-template-columns: 1fr;
}השוואה עם JavaScript
לפני :has, עיצוב מותנה לאלמנט הורה דרש שאילתות DOM ושינוי מחלקות ידנית. ההשגה של אותו אפקט של דוגמה 1 ב-JavaScript:
document.addEventListener("DOMContentLoaded", function() {
const divs = document.querySelectorAll('div');
divs.forEach(div => {
if (div.querySelector('img')) {
div.style.border = '2px solid green';
div.style.padding = '10px';
}
});
});
גרסת ה-CSS היא שורה בודדת. אבל מעבר לקיצור, יש הבדל מהותי: חוק ה-CSS הוא ריאקטיבי. אם תמונה נוספת או מוסרת מאוחר יותר, העיצוב מתעדכן מיידית. גרסת ה-JavaScript רצה פעם אחת בלבד בטעינת העמוד.
| היבט | CSS :has() | JavaScript |
|---|---|---|
| שורות קוד | 1-3 | +5-10 |
| ריאקטיבי לשינויי DOM | כן, אוטומטית | דורש MutationObserver |
| ביצועים | אופטימיזציה של הדפדפן | הרצת סקריפט + reflow |
| עובד ללא JS | כן | לא |
| לוגיקה מורכבת | לא | כן |
הסלקטור
:hasמהיר בדפדפנים מודרניים, אבל סלקטורים לא ממוקדים כמו:has(img)ללא קידומת טיפוס מכריחים את הדפדפן לבדוק כל אלמנט בעמוד. עדיף להשתמש בסלקטורים ממוקדים כמוdiv:has(img)וב-:has(> img)כשרוצים לטרגט רק צאצאים ישירים.
תמיכה בדפדפנים
הפסאודו-קלאס :has הגיע לסטטוס Baseline בדצמבר 2023 ונתמך כעת בכל הדפדפנים המרכזיים. Chrome 105+, Firefox 121+, Safari 15.4+ ו-Edge 105+ תומכים בו, עם כיסוי של מעל 96% מהמשתמשים ברחבי העולם נכון לתחילת 2026.
ניתן להשתמש ב-CSS @supports עם @supports selector(:has(*)) לזיהוי תכונות במקרה שנדרש fallback.
שאלות נפוצות
שאלות נפוצות על הסלקטור :has() ב-CSS:
:has() ב-CSS?
div:has(img) מטרגט כל div שמכיל אלמנט img.:has() נתמך בכל הדפדפנים?
:has() מחליף JavaScript לבחירת אלמנטים הורים?
:has() מטפל בעיצוב הורה-ילד ישירות ב-CSS ללא צורך בשאילתות DOM. הוא גם ריאקטיבי - עיצוב מתעדכן אוטומטית כשה-DOM משתנה. ל-JavaScript עדיין יש מקום עבור לוגיקה שמעבר לעיצוב.:has() משפיע על ביצועי העמוד?
:has(img) עלולים להאט את הרינדור כיוון שהדפדפן בודק כל אלמנט. השתמשו בקידומת טיפוס כמו div:has(img) וב-:has(> img) לטרגוט צאצאים ישירים בלבד.:has() עם פסאודו-קלאסים אחרים?
:has() משתלב היטב עם :not(), :is(), :where() ופסאודו-קלאסים של מצב כמו :checked או :invalid.:has() לבין :is()?
:is() מטרגט את האלמנט עצמו לפי רשימת סלקטורים. :has() מטרגט אלמנט לפי מה שהוא מכיל. לדוגמה, div:is(.red, .blue) מטרגט divs עם אותן מחלקות, בעוד div:has(.red) מטרגט divs שמכילים ילד עם מחלקה .red.סיכום
הפסאודו-קלאס :has נותן ל-CSS סלקטורים אמיתיים של אלמנטים הורים, יכולת שמפתחים חיכו לה שנים. תמיכת הדפדפנים אוניברסלית בשלב זה.
אם אתם מחפשים תכונות CSS מודרניות נוספות, כדאי להכיר את תכונת CSS Nesting או את תכונת mask-image.


