- Modern CSS Cheat Sheet — 20 פיצ'רים עם סטטוס תמיכה — טבלה מלאה של כל הפיצ'רים בפרק, מחולקת ל-4 Tiers (יציב / קצה-יציב / מתפתח / ניסיוני), עם סטטוס Chrome/Edge/Firefox/Safari, ותאריך last verified: אפריל 2026
- Component דמו עם Container Queries +
:has()— קוד CSS מלא של product card שמגיב לגודל הקונטיינר (לא ה-viewport) ומשנה צבע/layout כשיש בתוכו תמונה, טופס עם שגיאה, או checkbox מסומן - Modern CSS Prompt Template ל-AI — פרומפט באנגלית שמפרט ל-AI אילו פיצ'רים מודרניים להשתמש (עם שמות ספציפיים — Container Queries,
:has(),@layer,color-mix()), ואיזה CSS לא לכתוב (media queries במקום container queries, JavaScript להתנהגות שאפשר ב-:has()) - Progressive Enhancement Template — snippet של
@supportsעם fallback מוכן להעתיק-הדבק — נותן UX מלא לדפדפנים חדשים ו-UX בסיסי (שלא נשבר) לישנים - 4-Tier Decision Framework — flowchart של 4 שאלות ("האם כל 4 הדפדפנים תומכים?", "האם יש fallback טבעי?", "מה גודל פלח המשתמשים הפגועים?", "האם הפיצ'ר core או enhancement?") שיגיד לכם אם להשתמש בפיצ'ר עכשיו או לחכות
- רשימת 8 שימושים אמיתיים ל-
:has()— form validation, card states, empty states, conditional layouts, theme switching, active nav states, dropdown open state, sibling-aware styling - מילון של 21 מונחים — Container Queries,
@container,:has(), CSS nesting,@layer, cascade layers, subgrid,@scope, CSS Masonry, CSS Mixins,sibling-index(),corner-shape,superellipse,color-mix(),oklch(), anchor positioning, Popover API, browser support, progressive enhancement, Can I Use
- תוכלו להסביר מה עושים Container Queries ולבקש מ-AI להשתמש בהם במקום media queries ברכיבים — עם הבנה ברורה מתי container query עדיף (רכיב שמופיע במספר מקומות) ומתי media query עדיף (layout של כל הדף)
- תוכלו להנחות AI להשתמש ב-
:has()selector ליצירת התנהגויות דינמיות בלי JavaScript — form validation, card states, conditional layouts — עם 8 דוגמאות מעשיות ב-3 שורות CSS כל אחת - תוכלו לזהות מתי CSS nesting,
@layerו-@scopeמועילים ולבקש אותם בפרומפט — עם קריטריון מעשי (nesting להיררכיה < 3 רמות,@layerל-design system עם tokens+components+utilities,@scopeל-widgets שמתערבבים עם דפים אחרים) - תוכלו לדעת אילו פיצ'רים נתמכים בכל הדפדפנים ואילו צריכים fallback — עם workflow של 30 שניות ב-Can I Use ו-template של
@supportsprogressive enhancement שמגן על 5-10% מהמשתמשים מדפדפן ישן
- פרקים קודמים: פרק 5 חובה (Layout Mastery — הבנת CSS Grid ו-Flexbox, grid-template-areas, auto-fit/auto-fill). רוב הפיצ'רים בפרק הזה מניחים שאתם כבר חושבים ב-Grid. מומלץ גם פרק 3 (CSS custom properties / design tokens) ופרק 4 (responsive font sizes — clamp).
- מושגים שיחזרו: CSS Grid (פרק 5), CSS custom properties ו-design tokens (פרק 3), responsive font sizes עם
clamp()(פרק 4), whitespace ו-8px grid (פרק 5) - כלים: דפדפן עדכני (Chrome 120+, Edge 120+, Safari 17.4+, Firefox 121+) עם DevTools, חשבון ב-Can I Use (לא חייב — חינם וללא רישום), וכלי AI לבניית אתרים (Claude / Cursor / Bolt / Lovable / v0)
- אופציונלי אך מומלץ: StackBlitz או CodePen לנסות קוד מהר, ו-bram.us/2024 — הבלוג של Bramus Van Damme (Google DevRel) שמתעד כל פיצ'ר CSS חדש ברמת פירוט חובקת-הכל
- זמן משוער: 120-150 דקות (כולל 4 התרגילים ו-3 הפרומפטים שתנסו)
- חשוב לדעת: זה הפרק שפותח את פרקים 7 ו-8 — Scroll-Driven Animations ו-View Transitions — שניהם מניחים שאתם כבר מכירים את
@supportsואת דפוס ה-progressive enhancement מכאן
לאורך הקורס אתם בונים את היכולת להפוך אתר גנרי שAI בנה לאתר שנראה כמו עבודת סטודיו — ה-capstone בפרק 13. בפרק הקודם (5) הוספתם שליטה ב-Layout — CSS Grid, Flexbox, 8px spacing system, whitespace מכוון, ו-bento grid. עכשיו יש לכם "שלד" מקצועי. בפרק הזה (6) מוסיפים את ה-"שרירים": Container Queries שמאפשרים ל-component להיות responsive לבד, :has() שיוצר אינטראקטיביות בלי JS, @layer שמביא סדר לקוד של design system, ו-17 פיצ'רים נוספים. הפרק הזה הוא שער לשני פרקים מרכזיים: בפרק 7 (Scroll-Driven Animations) נשתמש באותו דפוס של @supports שלומדים כאן, ובפרק 8 (View Transitions API) נבנה על אותה הבנה של browser support וprogressive enhancement. בלי פרק 6 — פרקים 7 ו-8 לא יעבדו לכם.
| מונח (English) | תרגום | הגדרה בשורה אחת |
|---|---|---|
| Container Queries | שאילתות קונטיינר | סטיילינג שמגיב לגודל ה-קונטיינר של האלמנט (לא ה-viewport) — הופך components ל-responsive באמת |
@container | בלוק תנאי-קונטיינר | ה-at-rule שמחליף @media כשרוצים לבדוק רוחב קונטיינר במקום רוחב מסך |
:has() selector | סלקטור ה"מכיל" | סלקטור CSS שבודק אם לאלמנט יש ילד/צאצא מסוים — ה-"parent selector" שחיכינו לו 20 שנה |
| CSS Nesting | קינון CSS | כתיבה מקוננת ב-CSS native (ללא SASS/LESS) עם אופרטור & להתייחסות לסלקטור החיצוני |
@layer | שכבת Cascade | At-rule שיוצר שכבה של specificity — סטיילים בשכבות מאוחרות גוברים תמיד על מוקדמות, ללא קשר ל-specificity של הסלקטור |
| Cascade Layers | שכבות Cascade | המנגנון הכללי של @layer — סידור CSS לקבוצות מוגדרות (tokens → base → components → utilities) |
| Subgrid | תת-רשת | grid ילדים שיורשים את ה-tracks של ה-grid הורה — מאפשר יישור מושלם בין rows/columns ב-cards שונים |
@scope | בלוק מתוחם | At-rule שמגביל סטיילים לאזור ספציפי ב-DOM (@scope (.card) to (.card-content)) — style isolation ללא CSS-in-JS |
| CSS Masonry | Masonry מובנה | grid-template-rows: masonry — layout בסגנון Pinterest/Masonry ב-CSS טהור, ללא JavaScript libraries |
| CSS Mixins | מיקסינים | @mixin ו-@apply native של CSS — בלוק כללים שאפשר לשלב ב-selectors אחרים, כמו SASS אבל ב-browser |
sibling-index() | אינדקס אח | פונקציית CSS שמחזירה את מספר האלמנט בקרב אחיו — sibling-index() בתוך calc() יוצר סטיילינג דינמי לפי מיקום |
sibling-count() | ספירת אחים | פונקציית CSS שמחזירה את סך האחים — משמשת ליצירת distribution אחיד (למשל opacity שעולה לפי מיקום ב-list) |
corner-shape | צורת פינה | CSS property שמאפשר צורות פינה שונות מ-border-radius רגיל — concave, notch, scoop, squircle |
| Superellipse / Squircle | סופר-אליפסה / סקווירקל | צורה בין עיגול לריבוע — הפינה של Apple iOS: "עגולה יותר מעיגול אבל פחות מרובע" |
color-mix() | ערבוב צבעים | CSS function שמערבב שני צבעים באחוזים — color-mix(in oklch, red 60%, blue). מחליף מתמטיקה ידנית של RGB |
oklch() | מרחב צבע OKLCH | מרחב צבע perceptually uniform — הבהירות שקופה לעין אנושית (יתרון על HSL שלא אחיד perceptually) |
| Anchor Positioning | מיקום מעוגן | מיקום אלמנט ביחס לאלמנט אחר (anchor) — מחליף את Floating UI JS library ל-tooltips/dropdowns |
| Popover API | API פופאובר | HTML attribute popover + CSS ::backdrop — modals, tooltips, menus native, עם keyboard trap ו-Esc אוטומטי |
| Browser Support | תמיכת דפדפן | אחוז המשתמשים העולמי שדפדפנם תומך בפיצ'ר — בדיקה ב-Can I Use |
| Progressive Enhancement | שיפור הדרגתי | אסטרטגיה: נבנה UX בסיסי שעובד בכל הדפדפנים, ואז מוסיפים שכבה של שיפור לדפדפנים המודרניים באמצעות @supports |
| Can I Use | "אפשר להשתמש?" | האתר caniuse.com — מקור האמת לסטטוס תמיכה של פיצ'רי CSS/HTML/JS לפי דפדפן |
6.1 למה CSS של 2024-2026 הוא לא ה-CSS שאתם מכירים
ה-CSS ש-AI כותב כברירת-מחדל הוא CSS של 2015. זה לא קוד רע — הוא פשוט ישן. הוא משתמש ב-@media queries לכל responsive, ב-:nth-child() וב-+ sibling selectors במקום :has(), ב-calc() במקום clamp(), ב-RGB במקום oklch(), ובמרבית המקרים — ב-JavaScript לדברים ש-CSS כבר עושה בעצמו.
למה זה קורה? כי ה-training data של ה-AI מכיל כמויות אדירות של קוד ישן. גם ה-AIs המתקדמים ביותר נוטים ל-"ברירת-המחדל הבטוחה" — קוד שעובד בכל מקום, אבל נראה כמו שנכתב לפני 10 שנים. עד שלא תבקשו במפורש פיצ'ר מודרני — לא תקבלו אותו.
המטרה של הפרק הזה היא כפולה: (א) לדעת מה קיים — להכיר את 20 הפיצ'רים החדשים שמשנים הכל. (ב) לדעת איך לבקש — לנסח פרומפט שמכריח את ה-AI להשתמש בהם.
ההבדל ב-3 דוגמאות
דוגמה 1 — responsive card שמגיב לגודל שלו:
CSS של 2015 (AI default): מדידת window.innerWidth ב-JS, או @media (min-width: 768px) — אבל המדיה query לא יודע אם ה-card הוא ב-sidebar צר (250px) או ב-main רחב (1000px). התוצאה: ה-card בסיידבר נראה שבור.
CSS של 2026 (Modern): container-type: inline-size + @container (min-width: 400px) { ... }. ה-card יודע את הגודל של עצמו, בכל מקום.
דוגמה 2 — סטיילינג של form עם שגיאה:
CSS של 2015: הוספת class .error ל-form ב-JavaScript, הקשבה ל-events, state management מורכב — 50+ שורות קוד.
CSS של 2026: .form:has(input:invalid) { border-color: red; }. 2 שורות. אפס JavaScript.
דוגמה 3 — dropdown שמוצג כשלוחצים כפתור:
CSS של 2015: Floating UI library (3KB minified), Event listeners, position: absolute עם calculations של scroll/resize, accessibility manual.
CSS של 2026: <button popovertarget="menu"> + <div popover id="menu"> + anchor-name: --menu-anchor. HTML + 3 שורות CSS. Keyboard trap ו-Esc כבר מובנים.
ההבדל בין אתר שנראה "AI בנה" לאתר שנראה "סטודיו בנה" הוא לרוב לא באיכות הצבעים או הטיפוגרפיה — הוא במה שהאתר יודע לעשות בלי JavaScript. Container queries שגורמים לרכיבים להתנהג חכם בכל מקום, :has() שיוצר אינטראקטיביות בלי state, @layer שמונע מ-utilities לדרוס את ה-design system — כל אלה הופכים את הקוד לנכון ואת החוויה לחלקה. Vibe Coder שיודע את 20 הפיצ'רים האלה כותב אתרים שרצים מהר יותר, שוברים פחות, ונראים טוב יותר — כי הוא לא משתמש ב-JavaScript לדברים ש-CSS כבר עושה.
פתחו את האתר הגנרי שAI בנה לכם. לחצו F12 ועברו ל-tab Sources/Elements. חפשו @media ב-CSS. ספרו כמה יש. עכשיו חפשו @container. 90% מהסיכויים שיש 0. זה הפער. בסוף הפרק תדעו איך לבקש מ-AI להחליף 70% מה-@media ב-@container, ומה זה יעשה לאתר.
פתחו טאב חדש ב-caniuse.com/css-has. רשמו את ה-"Global" support percentage (אמור להיות 92%+ באפריל 2026). זה נתון הייחוס שלכם — :has() נתמך ב-92%+ מהדפדפנים בעולם, ולמרות זאת AI לא משתמש בו. זה בדיוק הפער שהפרק הזה סוגר.
6.2 מערכת ה-4 Tiers — איך לסווג כל פיצ'ר חדש
הבעיה עם "CSS מודרני" היא שהוא לא מוצר אחיד. יש פיצ'רים שתומכים בהם ב-96% מהדפדפנים (אפשר להשתמש בלי מחשבה), ויש כאלה שעדיין רק ב-Chrome Canary (חכו שנה). כדי לא לבלבל, אנחנו מסווגים כל פיצ'ר ל-אחד מ-4 Tiers:
| Tier | שם | Support | מה עושים? |
|---|---|---|---|
| Tier 1 | Stable — השתמשו עכשיו | 95%+ גלובלי, כל 4 הדפדפנים המרכזיים | השתמשו ללא fallback, ללא @supports, בכל פרויקט |
| Tier 2 | Cutting-edge Solid | 85-95% — Chrome/Edge מלא, Safari/Firefox זמינים אבל עדכניים | השתמשו עם @supports pattern כ-progressive enhancement — UX בסיסי ל-15% הישנים |
| Tier 3 | Emerging | 50-85% — Chrome 145+ בלבד, שאר הדפדפנים באחורה | השתמשו רק אם היתרון משמעותי, חובה fallback מלא, עדיפות לפרויקטים פנימיים |
| Tier 4 | Experimental / Meta | < 50% או behind a flag | למדו את הקונספט, אבל אל תשתמשו ב-production. בדקו מחדש כל 6 חודשים |
הסיווג של 20 הפיצ'רים בפרק (אפריל 2026)
הנה המפה המלאה של הפרק. שימו לב שהסטטוסים האלה משתנים מדי חודש — ה-cheat sheet שלכם חייב לכלול תאריך last-verified:
| פיצ'ר | Tier | Chrome | Edge | Safari | Firefox |
|---|---|---|---|---|---|
Container Queries (@container) | 1 | ✓ 105+ | ✓ 105+ | ✓ 16+ | ✓ 110+ |
:has() selector | 1 | ✓ 105+ | ✓ 105+ | ✓ 15.4+ | ✓ 121+ |
| CSS Nesting (native) | 1 | ✓ 112+ | ✓ 112+ | ✓ 16.5+ | ✓ 117+ |
@layer (Cascade Layers) | 1 | ✓ 99+ | ✓ 99+ | ✓ 15.4+ | ✓ 97+ |
color-mix() | 1 | ✓ 111+ | ✓ 111+ | ✓ 16.2+ | ✓ 113+ |
oklch()/oklab() | 1 | ✓ 111+ | ✓ 111+ | ✓ 15.4+ | ✓ 113+ |
clamp() | 1 | ✓ 79+ | ✓ 79+ | ✓ 13.1+ | ✓ 75+ |
| Subgrid | 2 | ✓ 117+ | ✓ 117+ | ✓ 16+ | ✓ 71+ |
@scope | 2 | ✓ 118+ | ✓ 118+ | בבנייה | בבנייה |
| Popover API | 2 | ✓ 114+ | ✓ 114+ | ✓ 17+ | ✓ 125+ |
| Anchor Positioning | 2 | ✓ 125+ | ✓ 125+ | בבנייה | בבנייה |
| Native CSS Masonry | 3 | ✓ 145+ (flag) | ✓ 145+ (flag) | מתוכנן | מתוכנן |
CSS Mixins (@mixin, @apply) | 3 | ✓ 145+ (flag) | ✓ 145+ (flag) | מתוכנן | מתוכנן |
sibling-index() / sibling-count() | 3 | ✓ 145+ | ✓ 145+ | מתוכנן | מתוכנן |
corner-shape / superellipse | 3 | ✓ 146+ (flag) | ✓ 146+ (flag) | מתוכנן | מתוכנן |
Last verified: אפריל 2026. הסטטוסים של שורות Tier 3 ככל הנראה ישתפרו משמעותית עד סוף 2026. בדקו ב-caniuse.com לפני כל פרויקט חדש.
ענו על 4 השאלות הבאות — יתנו לכם תשובה ברורה:
- האם כל 4 הדפדפנים המרכזיים תומכים? (Chrome, Edge, Safari, Firefox)
אם כן → Tier 1 — השתמשו בחופשיות.
אם לא → המשיכו לשאלה 2. - האם יש fallback טבעי? (למשל: Subgrid חוזר ל-Grid רגיל אם לא נתמך)
אם כן → Tier 2 — השתמשו עם@supports.
אם לא → המשיכו לשאלה 3. - מה גודל פלח המשתמשים שייפגעו? (בדקו Analytics או Google market share לפי שוק)
אם < 5% → Tier 2/3 — השתמשו עם fallback מינימלי.
אם 5-20% → Tier 3 — בנו fallback מלא שנותן UX טוב.
אם > 20% → Tier 4 — חכו. - האם הפיצ'ר core או enhancement? (האם בלעדיו האתר לא עובד, או רק לא נראה מדהים?)
Core → רק Tier 1.
Enhancement → Tier 1-3.
כלל אצבע: לפרויקט production רגיל (landing page, SaaS, e-commerce) — השתמשו ב-Tier 1 חופשי ו-Tier 2 עם @supports. לפרויקט ניסיוני / internal / portfolio — Tier 3 בסדר.
קחו את הפרויקט הפעיל שלכם. ענו על 4 השאלות למעלה ביחס לפיצ'ר הקרוב בליבכם — למשל :has(). רוב הסיכויים שתגיעו ל-Tier 1 וללא @supports. תיאוריה וחבל — זו החלטה של 30 שניות, ואם לא עשיתם אותה אתם חיים בפחד שווא.
הטעות המספר אחת בפרק הזה: לכתוב בפרומפט "use modern CSS" ולצפות שה-AI יבחר טוב. הוא לא יבחר. ה-default שלו הוא 2015. למה זה קורה: ה-training data שלו מכיל כמויות מסיביות של קוד ישן, ו-"modern" זה מונח מעורפל. מה לעשות במקום: רשמו שמות ספציפיים של פיצ'רים. "Use Container Queries (@container) instead of media queries where possible. Use :has() for parent states. Use @layer with layers: tokens, base, components, utilities. Use color-mix() in oklch color space." ה-AI יבצע. השם הספציפי הוא המפתח — בפרק 6.18 יש template מלא.
6.3 Container Queries — הפיצ'ר שהורס את media queries
אם הייתם צריכים ללמוד רק פיצ'ר אחד מהפרק הזה — זה. Container Queries (שאילתות קונטיינר) הן המהפכה הגדולה ב-responsive design מאז media queries ב-2008. הרעיון: במקום לבדוק את רוחב המסך, אנחנו בודקים את רוחב הקונטיינר שבו האלמנט יושב.
הבעיה שהן פותרות
דמיינו product card. אותו רכיב מופיע ב-3 מקומות באתר: (א) בסיידבר צר של 280px, (ב) ב-main grid של 4 עמודות של 300px כל אחת, (ג) ב-hero של עמוד product שתופס 1200px. עם media queries רגילות, ה-card הזה לא יכול לדעת אם הוא בסיידבר או ב-hero — הוא רק יודע את רוחב המסך. אם המסך רחב (desktop 1440px), הוא "חושב" שיש לו הרבה מקום — אבל בפועל הוא נדחק ל-280px בסיידבר ונשבר.
Container Queries פותרות את זה. ה-card שואל את הקונטיינר שלו: "כמה מקום יש לי?" ומקבל תשובה מדויקת. אותו רכיב, 3 התנהגויות שונות, בלי JavaScript ובלי variants.
ה-Syntax הבסיסי
/* שלב 1: מסמנים את האב כ"container" */
.card-wrapper {
container-type: inline-size;
container-name: card; /* optional — שם לשימוש ב-@container */
}
/* שלב 2: כותבים סטיילים על בסיס רוחב הקונטיינר */
.card {
display: flex;
flex-direction: column;
gap: 1rem;
}
@container card (min-width: 400px) {
.card {
flex-direction: row;
align-items: center;
gap: 1.5rem;
}
}
@container card (min-width: 600px) {
.card {
gap: 2rem;
}
.card img {
width: 40%;
}
}
תסתכלו על זה: אותו .card עובד בכל מקום. בסיידבר הוא column. ב-grid רחב הוא row. ב-hero הוא row עם תמונה גדולה. ה-HTML זהה. זה הקסם.
3 שימושים אמיתיים
שימוש 1: Product card ב-E-commerce
ה-card מופיע ב-search results (2 עמודות), recently viewed (4 עמודות), ו-product page (1 עמודה רחבה). Container queries מאפשרות לו לשנות layout מ-stacked (תמונה למעלה, טקסט למטה) ל-horizontal (תמונה בשמאל, טקסט בימין) ל-expanded (תמונה ענקית, טקסט מפורט) — לפי המקום שהוא מקבל.
שימוש 2: Sidebar widget
widget של "Recent articles" שאנשים שמים בסיידבר (200px) או ב-footer (1200px, 4 עמודות). ב-sidebar הוא stacked list. ב-footer הוא 4-column grid. Container query — שורה אחת.
שימוש 3: Embedded component (React/Web Component)
אם אתם בונים component library — למשל widget של לוח זמנים שמוטמע באתרים אחרים — אתם לא יודעים איפה הוא ימוקם. Container queries הם חובה: הרכיב מתאים את עצמו לכל גודל שמקבל, בלי לשאול אף אחד.
Container Query Units — cqw, cqh
בנוסף ל-@container, יש יחידות חדשות שמבוססות על הקונטיינר:
cqw— 1% מרוחב הקונטיינר (container query width)cqh— 1% מגובה הקונטיינרcqi— inline size (בכיוון הכתיבה — ב-RTL זה עדיין רוחב ברוב המקרים)cqb— block size
למשל, font-size: clamp(1rem, 3cqi, 2rem) — font שגודלו תלוי ב-container, לא ב-viewport. Genius.
השאלה שתעבוד 95% מהמקרים:
- Media Query (
@media): כשזה משפיע על layout של כל הדף. נווט מובייל ← deskop. Sidebar שמופיע/נעלם. Hero section שמשנה מבנה. Grid-level decisions. - Container Query (
@container): כשזה משפיע על רכיב יחיד שמופיע בכמה מקומות. Card, widget, embed, reusable component. Component-level decisions. - שילוב: Media query קובע את ה-grid של הדף. Container query קובע איך כל רכיב מתאים את עצמו בתוך תא ה-grid שקיבל.
פתחו CodePen חדש. העתיקו את הקוד של .card-wrapper + .card מהדוגמה. הוסיפו 3 wrappers ב-HTML — אחד ברוחב 250px, אחד 500px, אחד 900px. תראו איך אותו HTML של card משנה layout ב-3 המקומות. זה רגע ה-"aha" של הפרק. אם לא הרגשתם אותו — חזרו ועשו שוב. זה קריטי.
לא. הם משלימים זה את זה. Media query למקרו-layout (האם אני במובייל או desktop), Container query למיקרו-layout (איך ה-card הזה מסתדר במקום שקיבל). אם תחליפו את כל ה-@media ב-@container — תקבלו באגים, כי החלטות ברמת הדף (navbar, hero) לא שייכות לקונטיינר ספציפי. מה לעשות במקום: Media query להחלטות דף. Container query להחלטות רכיב. 70% מהרכיבים שלכם מתאימים ל-@container, 30% ל-@media.
6.4 :has() — הסלקטור שחיכינו לו 20 שנה
מ-1996 ועד 2022, ל-CSS היה חור גדול אחד: לא הייתה דרך לבחור אלמנט על בסיס הילדים שלו. יכולת לבחור child שיש לו parent מסוים (.parent .child), אבל לא להפך. ה-parent selector היה הבקשה הכי מבוקשת ב-CSS במשך שני עשורים.
ב-2022 הגיע :has() ופתר את זה. והוא עושה הרבה יותר מ"parent selector" — הוא מאפשר לבדוק כל קשר DOM: האם לאלמנט יש ילד? צאצא? אח (sibling) אחרי? אלמנט עם מצב ספציפי?
ה-Syntax
/* אלמנט X שיש לו ילד/צאצא Y */
X:has(Y) { ... }
/* .card שיש בתוכו img */
.card:has(img) {
padding-top: 0; /* בלי padding למעלה כי יש תמונה */
}
/* form שיש בו input לא-תקין */
form:has(input:invalid) {
border: 2px solid red;
}
/* section שיש אחריו section */
section:has(+ section) {
border-bottom: 1px solid var(--border);
}
8 שימושים מעשיים
1. Form validation — בלי JavaScript:
.field:has(input:invalid:not(:placeholder-shown)) {
--field-color: var(--danger);
}
.field:has(input:valid:not(:placeholder-shown)) {
--field-color: var(--success);
}
.field label { color: var(--field-color, var(--neutral)); }
.field input { border-color: var(--field-color, var(--neutral)); }
השדה משתנה צבע אדום/ירוק על בסיס תקינות הקלט. כולל :not(:placeholder-shown) כדי לא להציג שגיאה לפני שהמשתמש הקליד.
2. Card states — האם יש תמונה:
.card:has(img) .card-text { padding: 1rem; }
.card:not(:has(img)) .card-text { padding: 2rem; text-align: center; }
.card:not(:has(img)) { background: var(--gradient-primary); }
card עם תמונה: תמונה + טקסט רגיל. card בלי תמונה: רקע צבעוני + טקסט מרכזי. אותו HTML template. התנהגות חכמה.
3. Empty states — מצב "אין תוכן":
.list:not(:has(li)) {
display: block;
padding: 4rem;
text-align: center;
color: var(--muted);
}
.list:not(:has(li))::before {
content: "אין פריטים עדיין";
}
אם ה-list ריק — מוצג empty state. JS? לא. 5 שורות CSS.
4. Conditional layouts — sidebar אם יש aside:
main { grid-template-columns: 1fr; }
main:has(aside) { grid-template-columns: 1fr 280px; }
עיצוב הדף משתנה על בסיס נוכחות <aside>.
5. Theme switching — על בסיס toggle:
body:has(#dark-mode-toggle:checked) {
--bg: #0a0a0a;
--text: #fafafa;
}
toggle של dark mode ללא JavaScript. checkbox + :has() + custom properties.
6. Active nav state — על בסיס URL:
nav:has(a[href="/about"].active) .about-link {
font-weight: 700;
}
כל nav שמכיל link פעיל של /about — מדגיש אותו. (שילוב עם aria-current="page" נפוץ גם.)
7. Dropdown open state:
.dropdown:has(.menu[aria-expanded="true"]) {
background: var(--hover-bg);
}
.dropdown:has(.menu[aria-expanded="true"]) .arrow {
transform: rotate(180deg);
}
כש-dropdown פתוח — החצים והרקע מתעדכנים. בלי לגעת ב-state management.
8. Sibling-aware styling:
article:has(+ article) {
margin-bottom: 2rem;
border-bottom: 1px solid var(--border);
}
אם יש article אחריו — הוסף margin+border. אם זה האחרון — לא. זה פותר את הבעיה הקלאסית של "הפרדה בין items בלי הפרדה אחרי האחרון".
Performance — האם :has() איטי?
שאלה נפוצה: האם selector שמסתכל על ילדים לא יהיה לאט? התשובה: לא. המנועים המודרניים (Blink, WebKit, Gecko) אופטימיזו :has() למקרי שימוש פרקטיים — הוא רץ כמו כל selector אחר ברוב המקרים. המקרים היחידים שבהם אפשר לראות איטיות: :has() על עץ עמוק מאוד (1000+ אלמנטים) עם שינויי DOM תכופים. ברוב האתרים — לא תרגישו הבדל.
:has() ומתי JavaScript?
- השתמשו ב-
:has(): מצב ויזואלי שנשלט על-ידי ילד (checkbox, input state, aria attributes, נוכחות של ילד). - השתמשו ב-JavaScript: תגובה ל-events (click, scroll, resize), תקשורת עם backend, state מורכב שעובר בין רכיבים לא-קרובים.
- כלל אצבע: אם אתם יכולים לייצג את ה-state כ-HTML (checkbox, data-attribute, aria) —
:has()ינצח. אם לא — JS.
קחו את דוגמה 1 (Form validation). העתיקו ל-CodePen. בנו form עם 2 שדות (email + טלפון). השאירו את ה-validation לדפדפן (type="email", required). הוסיפו את ה-CSS של :has(input:invalid). הקלידו טקסט לא-תקין בשדה. ראו איך השדה משנה צבע ללא JS. זה ה-moment שאחריו לא תחזרו ל-JS validation.
פתחו את האתר שלכם. חפשו event listeners ב-JavaScript שמשנים classes של אלמנטים על בסיס מצב של ילדים (active, hasImage, isEmpty). רשמו 2-3 מהם. אלה המקרים שאפשר להחליף ב-:has(). שמרו את הרשימה — תגשו אליה בתרגילים.
6.5 CSS Nesting — SASS בלי SASS
עשרים שנה השתמשו מפתחים ב-SASS/LESS/PostCSS רק בשביל דבר אחד: לכתוב CSS מקונן. נגמר. CSS Nesting native נתמך בכל הדפדפנים מ-2023, ואתם לא צריכים יותר preprocessor בשביל זה.
לפני ואחרי
/* CSS של 2015 — שטוח */
.card { padding: 1rem; border-radius: 0.5rem; }
.card h2 { margin-bottom: 0.5rem; }
.card p { color: var(--muted); }
.card:hover { box-shadow: var(--shadow-md); }
.card.featured { border: 2px solid var(--primary); }
.card.featured h2 { color: var(--primary); }
/* CSS של 2026 — מקונן, native */
.card {
padding: 1rem;
border-radius: 0.5rem;
& h2 { margin-bottom: 0.5rem; }
& p { color: var(--muted); }
&:hover { box-shadow: var(--shadow-md); }
&.featured {
border: 2px solid var(--primary);
& h2 { color: var(--primary); }
}
}
הכלל של ה-&
האופרטור & מייצג את ה-selector החיצוני. &:hover שווה ל-.card:hover. &.featured שווה ל-.card.featured. כדי להימנע מ-ambiguity, הפרשנות של CSS Nesting דורשת & במקרים מסוימים — הכי בטוח להשתמש בו תמיד.
כלל הזהב: לא יותר מ-3 רמות
Nesting הוא נשק דו-פני. אם תקוננו 5 רמות עמוק, תקבלו specificity wars שאתם לא יכולים לפתור. הכלל: עד 3 רמות. אם הגעתם ל-4, תחלקו לקלאסים נפרדים.
קחו קובץ CSS שטוח של הפרויקט שלכם. בחרו רכיב אחד (כרטיס, navbar, footer). המירו את כל ה-selectors שלו ל-nested syntax עם &. תראו איך הקוד מתקצר ב-30-40% והופך קריא יותר.
6.6 @layer — סוף מלחמות ה-specificity
אם כתבתם CSS עד היום, אתם מכירים את זה: !important שדורס !important אחר. שני .class שדוחים #id. Utility classes של Tailwind שמפסידים ל-component CSS. זה specificity war, והוא אחת הסיבות העיקריות למה CSS "מרגיש שבור".
Cascade Layers (@layer) פותרים את זה אחת ולתמיד. הרעיון פשוט: מה שבשכבה מאוחרת יותר תמיד גובר, ללא קשר ל-specificity של הסלקטור. שכבות נקבעות בסדר מפורש.
הדפוס המומלץ — 4 שכבות
/* הצהרת השכבות — קובעת את הסדר. קריטי! */
@layer tokens, base, components, utilities;
/* שכבה 1: Design Tokens — CSS custom properties */
@layer tokens {
:root {
--color-primary: oklch(55% 0.2 250);
--space-1: 0.5rem;
--space-2: 1rem;
}
}
/* שכבה 2: Base — reset ו-defaults */
@layer base {
* { box-sizing: border-box; }
body { font-family: Heebo, sans-serif; line-height: 1.6; }
a { color: var(--color-primary); }
}
/* שכבה 3: Components — רכיבים בנויים */
@layer components {
.card {
padding: var(--space-3);
border-radius: 0.75rem;
background: var(--bg-card);
}
.button-primary {
background: var(--color-primary);
color: white;
}
}
/* שכבה 4: Utilities — דריסות נקודתיות (Tailwind-style) */
@layer utilities {
.mt-4 { margin-top: var(--space-4); }
.text-center { text-align: center; }
.hidden { display: none; }
}
למה זה משנה הכל
עכשיו .mt-4 (utility) תמיד גובר על .card (component), בלי !important. אפילו אם ה-utility הוא סלקטור של 1 קלאס וה-component הוא סלקטור של 3 קלאסים — ה-utility ב-layer מאוחר יותר, ולכן ינצח. זה הופך את ה-CSS לצפוי.
מתי להשתמש ב-@layer
- חובה: בפרויקטים עם design system (tokens + components + utilities)
- חובה: כשמשתמשים בספריית UI חיצונית (shadcn, Material UI) + CSS מותאם אישית — עטפו את הספרייה ב-layer נפרד
- מועיל: בכל פרויקט מעל 500 שורות CSS
- overkill: ב-landing page של 100 שורות
6.7 color-mix() ו-oklch() — הצבעים של 2026
אם פרק 3 נתן לכם פלטת צבעים — הפרק הזה נותן לכם את השפה המודרנית לעבוד עם צבעים. שתי פונקציות חדשות משנות הכל:
1. color-mix() — ערבוב מכני של צבעים
/* ערבוב 60% אדום עם 40% כחול במרחב oklch */
background: color-mix(in oklch, red 60%, blue);
/* ליצור variants של ה-primary color */
--primary-light: color-mix(in oklch, var(--primary) 70%, white);
--primary-dark: color-mix(in oklch, var(--primary) 70%, black);
--primary-muted: color-mix(in oklch, var(--primary) 20%, transparent);
/* hover state — primary עם שכבת שקיפות */
.button:hover {
background: color-mix(in oklch, var(--primary) 90%, black);
}
זה מחליף חישובי RGB ידניים, ספריות JS של color manipulation, ו-SASS lighten()/darken(). פחות מתמטיקה, יותר שליטה.
2. oklch() — מרחב צבע שהעין רואה נכון
HSL (Hue, Saturation, Lightness) היה הסטנדרט במשך 15 שנה. הבעיה: Lightness ב-HSL לא נתפס אחיד על-ידי העין האנושית. צהוב עם L=50% נראה בהיר בהרבה מסגול עם L=50%. זה הופך design systems לכאב ראש — אם תרצו ליצור גרדאציה אחידה של בהירות, תצטרכו לחשב ידנית.
OKLCH (OK Lightness Chroma Hue) פותר את זה. הבהירות אחידה perceptually. L=50% נראה זהה בבהירות בכל גוון. זה הופך את בניית ה-palette לקלה ועקבית.
/* Palette עם 5 רמות בהירות — כל שורה באותה בהירות חזותית */
--gray-100: oklch(95% 0.005 250);
--gray-300: oklch(85% 0.008 250);
--gray-500: oklch(60% 0.012 250);
--gray-700: oklch(35% 0.015 250);
--gray-900: oklch(15% 0.018 250);
/* Primary, secondary, accent — באותה בהירות */
--primary: oklch(60% 0.18 250); /* כחול */
--secondary: oklch(60% 0.18 20); /* כתום — באותה בהירות */
--accent: oklch(60% 0.18 140); /* ירוק — באותה בהירות */
שלושת הפרמטרים של oklch()
- L (Lightness): 0-100% — 0 שחור, 100 לבן. perceptually uniform.
- C (Chroma): 0-0.4 לרוב — 0 אפור, ערכים גבוהים = רווי יותר. אין "מקס" אבנורמלי — תלוי בגוון ובדפדפן.
- H (Hue): 0-360 — גלגל הצבעים. 0 אדום, 90 צהוב, 180 ציאן, 270 סגול.
השתמשו ב-oklch.com — כלי אונליין שממיר את הצבע הנוכחי שלכם ל-OKLCH, מראה לכם את ה-palette במרחב הזה, ומאפשר "לסובב" את הגוון בלי לשנות בהירות. זה מה שמעצבים של 2026 משתמשים בו.
6.8 Subgrid — יישור מושלם בין grid items
הבעיה: יש לכם row של 4 cards. בכל card יש: כותרת, תיאור, מחיר, כפתור. הכותרות באורך שונה — חלקן שורה אחת, חלקן שתיים. זה גורם לתיאור ב-card עם כותרת קצרה להתחיל "גבוה יותר" מאשר ב-card עם כותרת ארוכה. ה-cards לא מיושרים.
Subgrid פותר את זה. במקום שכל card יהיה grid עצמאי — הוא יורש את ה-rows מה-grid הורה. כל הכותרות בשורה אחת, כל התיאורים בשורה אחרת, כל המחירים בשורה אחרת, כל הכפתורים בשורה אחרת. יישור מושלם.
הקוד
.card-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: auto auto auto auto; /* title, desc, price, button */
gap: var(--space-3);
}
.card {
display: grid;
/* הקסם: יורש את ה-rows מה-parent */
grid-template-rows: subgrid;
grid-row: span 4; /* התופס 4 שורות של ה-parent */
gap: 0.5rem;
}
.card h3 { grid-row: 1; }
.card p { grid-row: 2; }
.card .price { grid-row: 3; }
.card button { grid-row: 4; }
התוצאה: יש לכם 4 "שורות וירטואליות" שגולשות על פני כל ה-cards. כל אלמנט עם grid-row: N יהיה באותו גובה באופקי. זה מה שלא היה אפשר בלי subgrid.
6.9 @scope — הגבלת סטיילים לאזור ב-DOM
פיצ'ר מתקדם יותר. @scope יוצר "גבול" ל-CSS — הוא חל רק על אלמנטים בתוך אזור מוגדר של ה-DOM. זה פותר את הבעיה של widgets שמשתלבים באתרים אחרים או components עם style isolation.
/* כל ה-CSS הזה חל רק בתוך .shopping-cart */
@scope (.shopping-cart) {
:scope { padding: 1.5rem; }
.item { border-bottom: 1px solid var(--border); }
.price { font-weight: 700; color: var(--primary); }
}
/* Scope עם "Lower boundary" — חל מ-.article עד ל-.comments */
@scope (.article) to (.comments) {
/* כאן כללים שחלים בתוך article אבל לא נכנסים לאזור תגובות */
p { font-size: 1.125rem; line-height: 1.75; }
}
זה בעצם CSS Modules ללא build step. שימושי למי שבונה widgets, לא לרוב הפרויקטים.
Tier 2 באפריל 2026 — Chrome/Edge מלא, Safari/Firefox בבנייה. אם זה קריטי — @supports selector(:scope) ל-fallback.
6.10 Popover API — modals ו-tooltips ללא JavaScript
Popover API הוא אחד הפיצ'רים הכי חמים של 2024-2026. הוא מביא modals, tooltips, context menus, ו-dropdowns כ-HTML native — עם keyboard traps, Esc support, ו-click-outside handling מובנים.
דוגמה מינימלית
<!-- כפתור שפותח פופאובר -->
<button popovertarget="user-menu">תפריט משתמש</button>
<!-- הפופאובר עצמו -->
<div id="user-menu" popover>
<a href="/profile">הפרופיל שלי</a>
<a href="/settings">הגדרות</a>
<button popovertarget="user-menu" popovertargetaction="hide">סגור</button>
</div>
זה הכל. אפס JavaScript. הדפדפן מטפל ב:
- פתיחה/סגירה בלחיצה על הכפתור
- סגירה ב-Esc
- סגירה בלחיצה מחוץ לפופאובר (auto mode)
- Keyboard navigation עם Tab
- Focus management — מחזיר focus לכפתור כשסוגרים
- Accessibility — ARIA attributes מובנים
2 סוגי Popover
popover="auto"(ברירת-מחדל) — רק אחד פתוח בכל רגע, light dismiss (לחיצה מחוץ סוגרת).popover="manual"— כמה פתוחים בו-זמנית, לא נסגר אוטומטית — לתזכורות/טוסטים.
Styling עם ::backdrop
[popover] {
padding: 1.5rem;
border: none;
border-radius: 1rem;
box-shadow: var(--shadow-xl);
}
/* הרקע שמאחורי — כשה-popover פתוח */
[popover]::backdrop {
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(4px);
}
צרו HTML חדש. הדביקו את ה-code של "דוגמה מינימלית" של Popover. פתחו בדפדפן. לחצו על הכפתור. ראו שהתפריט נפתח. לחצו Esc. ראו שהוא נסגר. לחצו מחוץ. ראו שהוא נסגר. בלי JavaScript. זה הרגע שמרגישים את CSS של 2026.
6.11 Anchor Positioning — סוף לספריית Floating UI
Floating UI (לשעבר Popper.js) היא ספרייה של ~10KB שכמעט כל אתר מודרני משתמש בה כדי למקם tooltips, dropdowns, popovers ליד כפתורים. Anchor Positioning מחליף אותה. CSS טהור.
/* הכפתור משמש כ-anchor */
button.help-btn {
anchor-name: --help-anchor;
}
/* ה-tooltip "מתחבר" ל-anchor */
.help-tooltip {
position: absolute;
position-anchor: --help-anchor;
/* ממוקם למעלה של ה-anchor, ממורכז אופקית */
top: anchor(top);
left: anchor(center);
translate: -50% -100%;
/* מרווח של 8px מה-anchor */
margin-bottom: 8px;
}
/* Auto fallback — אם אין מקום למעלה, תעבור למטה */
.help-tooltip {
position-try: flip-block;
}
זה מחליף חישובי JS של getBoundingClientRect, scroll/resize listeners, ו-reposition logic. CSS טהור, יותר מהיר, פחות קוד.
סטטוס אפריל 2026: Tier 2 — Chrome 125+/Edge 125+ מלא. Safari/Firefox בבנייה. @supports (position-anchor: --x) לבדיקה.
6.12 Native CSS Masonry — Pinterest ב-CSS טהור
Masonry הוא layout שבו אלמנטים בגבהים שונים "נופלים" לעמודות באופן אופטימלי — כמו Pinterest. עד 2025, זה דרש JavaScript (Masonry.js, Isotope). עכשיו CSS עושה את זה לבד.
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-template-rows: masonry; /* זה הקסם */
gap: 1rem;
}
שורה אחת. פחות שורה בעצם — שינוי של grid-template-rows ל-masonry. האלמנטים "נופלים" לעמודה הקצרה ביותר בכל פעם. Pinterest layout מלא.
Tier 3 באפריל 2026 — Chrome 145+ מאחורי flag. שאר הדפדפנים מתוכננים. עד שיהיה יציב — השתמשו ב-columns: 3 + column-gap כ-fallback (לא אותו דבר, אבל דומה).
6.13 CSS Mixins (@mixin, @apply) — reusable patterns native
עוד פיצ'ר שגוזל את SASS. Mixins הם "פונקציות CSS" — בלוק של כללים שאפשר "להחיל" על selector אחר.
/* הגדרת mixin */
@mixin card-base {
padding: 1.5rem;
border-radius: 1rem;
background: var(--bg-card);
box-shadow: var(--shadow-sm);
transition: box-shadow 0.2s;
}
/* שימוש */
.product-card {
@apply card-base;
border: 1px solid var(--border);
}
.article-card {
@apply card-base;
max-width: 42rem;
}
Tier 3 — Chrome 145+ מאחורי flag. עד שיציב — Tailwind @apply הוא ה-alternative (אבל זה build-step, לא native). --var: paren-value עם @property הוא פתרון ביניים.
6.14 sibling-index() ו-sibling-count() — סטיילינג דינמי לפי מיקום
עד 2025, אם רציתם לסטייל אלמנטים על בסיס מיקומם במערך אחים, הייתם צריכים :nth-child(1), :nth-child(2) וכו' — מדרגה-מדרגה ידנית. sibling-index() ו-sibling-count() הופכים את זה לחישוב דינמי.
/* כל פריט ב-list — opacity דינמי לפי מיקום */
.list-item {
opacity: calc(1 - (sibling-index() - 1) / sibling-count() * 0.5);
/* הפריט הראשון — opacity 1, האחרון — 0.5 */
}
/* animation delay מדורג */
.card {
animation: slide-in 0.6s ease forwards;
animation-delay: calc(sibling-index() * 0.1s);
/* card ראשון — 0ms, שני — 100ms, שלישי — 200ms... */
}
זה הרבה יותר אלגנטי מ-:nth-child(1) { ... } :nth-child(2) { ... } של 10 שורות. Tier 3 — Chrome 145+ באפריל 2026. @supports fallback.
6.15 corner-shape ו-superellipse — squircles בסגנון Apple
אם הסתכלתם על אייקון iOS אי-פעם — הפינות שלו "מעוגלות יותר מעיגול". זה נקרא squircle (square + circle), או מתמטית — superellipse. הפינה עוברת יותר בחלקות מהצלע לעקומה.
עד 2025, זה דרש SVG או JavaScript. עכשיו:
.ios-icon {
border-radius: 20%;
corner-shape: superellipse(2.5);
/* הערך 2.5 = squircle "עגול יותר מעיגול" */
/* superellipse(2) = עיגול רגיל */
/* superellipse(4) = יותר מרובע */
/* superellipse(infinity) = ריבוע חד */
}
הערך 2-2.5 נותן את ה-look של iOS. Tier 3 — Chrome 146+ מאחורי flag באפריל 2026. fallback — border-radius רגיל נראה "בסדר" גם בלי.
אתם רואים דוגמה של corner-shape ב-Twitter, מתלהבים, ומוסיפים ל-production. 5-10% מהמשתמשים שלכם רואים ריבוע חד במקום squircle — זה עדיין נראה סביר. אבל אם הפיצ'ר קריטי (Popover API שפותח תפריט, :has() שמציג שגיאה) — 5-10% של משתמשים לא יוכלו להשתמש באתר. מה לעשות במקום: Tier 2-3 תמיד עם @supports. Tier 1 בלי חשש. ההכרעה: האם בלי הפיצ'ר — האתר עובד? אם לא — לא בלי @supports.
6.16 Can I Use — איך לבדוק support ב-30 שניות
האתר caniuse.com הוא מקור האמת של עולם ה-web. לפני כל פיצ'ר חדש — בדקו שם. ה-workflow של 30 שניות:
- גשו ל-
caniuse.com/<feature-name>(למשלcaniuse.com/css-has) - חפשו את "Global" percentage בראש העמוד. זה אחוז המשתמשים העולמי שדפדפנם תומך
- סתכלו על טבלת הדפדפנים. ירוק = תומך. אדום = לא. כתום = עם prefix או behind flag
- בדקו "Notes & Known issues" למטה — יש תמיד גאצ'ות
- קבלו החלטה לפי 4-Tier framework שלכם
דוגמה — :has() באפריל 2026
- Global: ~92%
- Chrome 105+ ✓, Edge 105+ ✓, Safari 15.4+ ✓, Firefox 121+ ✓
- החלטה: Tier 1. השתמשו בחופשיות.
דוגמה — CSS Masonry
- Global: ~50% (Chrome 145+ בלבד, מאחורי flag)
- החלטה: Tier 3. חכו או בנו עם fallback של
columns.
בחרו 3 פיצ'רים מהפרק: :has(), Container Queries, Subgrid. בדקו כל אחד ב-caniuse.com. רשמו את ה-Global percentage והחליטו Tier. זה השריר שאתם בונים — לפני כל שימוש בפיצ'ר חדש, 30 שניות ב-caniuse.
6.17 @supports — Progressive Enhancement שלא שובר כלום
Progressive Enhancement (שיפור הדרגתי) היא אסטרטגיה: בונים קודם UX בסיסי שעובד בכל הדפדפנים, ואז מוסיפים שכבה של שיפור לדפדפנים שתומכים בפיצ'רים חדשים. ה-at-rule @supports הוא הכלי.
ה-Syntax
/* בסיס — עובד בכל הדפדפנים */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
}
/* שיפור — רק אם הדפדפן תומך ב-masonry */
@supports (grid-template-rows: masonry) {
.gallery {
grid-template-rows: masonry;
}
}
Template מוכן להעתקה
/* ===== PROGRESSIVE ENHANCEMENT TEMPLATE ===== */
/* 1. BASELINE — UX בסיסי לכולם */
.modal {
/* בסיס עם JavaScript toggle */
display: none;
position: fixed; inset: 0;
background: white; padding: 2rem;
}
.modal.is-open { display: block; }
/* 2. ENHANCED — Popover API לדפדפנים שתומכים */
@supports selector(:popover-open) {
/* כאן: שימוש ב-popover HTML attribute במקום class toggle */
.modal[popover] { /* styles */ }
/* JS יכול להשתמש ב-.showPopover() במקום להוסיף class */
}
/* 3. ENHANCED+ — anchor positioning */
@supports (position-anchor: --x) {
.tooltip {
position: absolute;
position-anchor: --help-anchor;
top: anchor(top);
}
}
/* 4. ENHANCED++ — container queries */
@supports (container-type: inline-size) {
.card-wrapper { container-type: inline-size; }
@container (min-width: 400px) {
.card { flex-direction: row; }
}
}
3 סוגי @supports
@supports (property: value)— בודק property/value (הכי נפוץ)@supports selector(:has(*))— בודק selector (ל-:has,:popover-open)@supports not (container-type: inline-size)— בודק אי-תמיכה (שימושי ל-fallbacks)
קחו רכיב אחד בפרויקט שלכם שיכול להשתפר עם Container Query (למשל product card). כתבו את ה-CSS הבסיסי שעובד בלי. הוסיפו @supports (container-type: inline-size) עם השיפור. פתחו ב-Chrome (יראה שיפור) ואז ב-Safari 14 (לא תומך — יראה fallback). זה progressive enhancement בפועל.
6.18 Modern CSS Prompt — איך לכפות על AI לכתוב CSS של 2026
זה ה-deliverable המרכזי של הפרק. פרומפט מובנה שתוכלו להעתיק-להדביק לתחילת כל פרויקט AI, שמכריח את הכלי להשתמש ב-CSS של 2026 ולא של 2015.
Modern CSS Prompt Template v1.0 (English for AI tools)
MODERN CSS REQUIREMENTS — Use these features by name. Do not substitute with older alternatives:
Layout & Responsiveness:
- For COMPONENT responsiveness (cards, widgets, embeds) use Container Queries withcontainer-type: inline-sizeand@container (min-width: N) {...}. Do NOT use@mediafor component-level responsive.
- For PAGE-LEVEL responsiveness (navbar, sidebar, hero), use@media.
- For card rows requiring alignment, use subgrid:grid-template-rows: subgrid.
Selectors & State:
- Use:has()for parent/ancestor state: form validation (.field:has(input:invalid)), card variants (.card:has(img)), empty states (.list:not(:has(li)))), conditional layouts.
- Do NOT use JavaScript for state that can be expressed via HTML (checkbox +:has(), aria-attributes +:has()).
Structure:
- Use CSS Nesting with&operator. Max 3 levels deep.
- Use@layerwith this exact order:@layer tokens, base, components, utilities;.
- Wrap design tokens in@layer tokens, components in@layer components, utilities/Tailwind-style helpers in@layer utilities.
Colors:
- Useoklch()color space for all palette definitions. Do NOT use HSL for new palettes.
- Usecolor-mix(in oklch, X N%, Y)for variants (lighter/darker/muted). Do NOT use manual RGB math.
- Hover/active states:color-mix(in oklch, var(--primary) 90%, black).
UI Components:
- For modals, dropdowns, tooltips, context menus — use Popover API (HTMLpopoverattribute +popovertarget).
- For positioning relative to another element (tooltips, dropdowns) — use Anchor Positioning (anchor-name,position-anchor,anchor()). Do NOT use Floating UI library.
- Use::backdropwithbackdrop-filter: blur()for modal overlays.
Fluid sizing:
- Useclamp(min, fluid, max)for responsive font-sizes and spacing. Do NOT use multiple media queries for this.
- Prefercqiunits inclamp()when sizing inside a container-typed element.
Progressive Enhancement:
- For features beyond baseline (Tier 2-3), use@supportsto add enhancements without breaking older browsers.
- For:has():@supports selector(:has(*)).
- For container queries:@supports (container-type: inline-size).
DO NOT (anti-patterns that AI defaults to):
- Do NOT use@mediainside a component — use@container.
- Do NOT use JavaScript to toggle classes when:has()can read HTML state.
- Do NOT use SASS/LESS@importor nesting — use native CSS Nesting.
- Do NOT use HSL for new color palettes — use OKLCH.
- Do NOT use Floating UI, Popper, or manualgetBoundingClientRect— use Anchor Positioning.
- Do NOT useposition: fixed+ manual focus trap for modals — use Popover API.
- Do NOT use!important— use@layerordering instead.
Browser Support Baseline (last verified: April 2026):
- Target: Chrome 120+, Edge 120+, Safari 17+, Firefox 121+
- All Tier 1 features work. Tier 2-3 need@supports.
QUALITY GATE:
Before delivering, audit the CSS: (1) Is there any@mediathat should be@container? (2) Is there any JavaScript class-toggle that can be:has()? (3) Are colors inoklch()? (4) Are there@layerdeclarations? (5) Is there an Anchor Positioning block instead of JS positioning? (6) Are modals usingpopoverattribute? If any answer is "no", check if you should refactor.
4 שלבי ההתאמה האישית
- Target browsers: אם הפרויקט צריך לתמוך ב-IE11 (נדיר מאוד ב-2026) — הסירו את Tier 2-3. אחרת — השאירו הכל.
- אילו פיצ'רים ב-Tier 2 לאשר? Popover ו-Subgrid — תמיד. Anchor Positioning — רק אם יש ספרייה שעדיין משתמשים בה.
@scope— אם יש צורך ב-isolation. - Progressive Enhancement — להשאיר או להסיר: לפרויקט עם 5%+ פלח של משתמשים ישנים — להשאיר. לפרויקט internal/portfolio — אפשר להסיר ולהיות Chrome-first.
- Quality gate — תמיד להשאיר: זה מה שמאלץ את ה-AI לבדוק את עצמו בסוף.
העתיקו את ה-Modern CSS Prompt. שלבו אותו עם ה-Layout Spec מפרק 5 + Color Palette מפרק 3 + Typography Spec מפרק 4. זה design brief מלא של 2026. שמרו. תשתמשו בזה בתרגיל האחרון של הפרק.
- פתחו פרויקט שלכם. רשמו את 5 הרכיבים המרכזיים (למשל: card, navbar, form, hero, sidebar).
- לכל רכיב, רשמו: האם הוא מופיע בכמה מקומות שונים? מה הגדלים השונים?
- סיווגו: אם הרכיב מופיע ב-2+ גדלים שונים באותה עמודה של פרויקט — הוא מועמד ל-
@container. אחרת@media. - בחרו את הרכיב הראשון שמתאים ל-
@container— סביר שזה card. - הוסיפו
container-type: inline-sizeל-wrapper. העבירו לפחות 2 media queries שלו ל-@container. - בדקו ב-DevTools שהרכיב עובד נכון ב-3 גדלים שונים (הקטינו את ה-wrapper ידנית ב-DevTools).
- בדקו שה-wrapper ב-sidebar צר נותן layout אחר מאשר ב-main רחב.
מה צריך להיות בסוף: מסמך של טבלת 5 רכיבים עם סיווג (@media/@container), רכיב אחד שהומר, 3 screenshots של אותו רכיב ב-3 גדלים, ורשימת 2-3 תובנות שהגעתם אליהן.
:has()
25 דקות
- פתחו את קוד ה-JavaScript של הפרויקט שלכם. חפשו:
classList.add,classList.toggle,setAttribute— כל מה שמוסיף/מסיר state-class. - רשמו 3 מקרים כאלה. למשל: "add
.has-imageto card when img exists", "add.errorto form when input invalid", "add.opento dropdown on click". - לכל מקרה — בדקו: האם ה-state נובע מ-HTML שאפשר לבטא? (img exists →
:has(img), input invalid →:has(input:invalid), dropdown open → אפשר עם:has(.menu[aria-expanded="true"])). - בחרו את המקרה הכי קל מה-3. הסירו את ה-JavaScript שמטפל בו.
- כתבו את ה-CSS עם
:has(). - בדקו שההתנהגות זהה — אבל עם 0 שורות JS.
- מדדו את ה-bundle size לפני ואחרי. אמור להיות קטן ב-kilobytes בודדים.
מה צריך להיות בסוף: רשימת 3 מקרים של JS class-toggle, מקרה אחד שהומר ל-:has(), השוואת bundle size, והבנה כמה JS נוסף אפשר להסיר.
@layer Architecture
30 דקות
- פתחו את קובץ ה-CSS של הפרויקט שלכם.
- בראש הקובץ, הוסיפו:
@layer tokens, base, components, utilities; - עברו על ה-CSS וסווגו כל בלוק לאחת מ-4 השכבות:
- tokens:
:root { --color-*, --space-* }וכל custom properties - base: reset, defaults של body/html, סטיילינג גלובלי של
a,h1-h6 - components:
.card,.button,.nav— רכיבים - utilities:
.mt-*,.text-center,.hidden— מחלקות helper
- tokens:
- עטפו כל קבוצה ב-
@layer X { ... }. - הסירו את כל ה-
!important— עכשיו ה-layer order מטפל בלוגיקת ה-override. - בדקו שהאתר עדיין עובד נכון. אם יש דבר שלא נראה — בדקו שה-utility שעובר על component נמצא ב-layer מאוחר יותר.
- רעננו. אמור להיראות זהה — אבל הקוד הרבה יותר ניתן לתחזוקה.
מה צריך להיות בסוף: קובץ CSS מחולק ל-4 layers, 0 מופעים של !important, רשימה של 3-5 שיפורי תחזוקה שה-layers מאפשרים.
- קחו את ה-Modern CSS Prompt מ-section 6.18. התאימו: בחרו target browsers, בחרו אילו Tier 2 לאשר, החליטו על progressive enhancement.
- שלבו עם פרומפטים קודמים: Layout Spec (פרק 5) + Color Palette (פרק 3) + Typography Spec (פרק 4).
- הריצו בכלי AI. בקשו "build a product card component with image, title, description, price, and a 'Add to cart' button. The card should adapt to its container: in sidebar (280px) — stacked; in grid (400px) — horizontal; in featured area (800px) — expanded with large image".
- קבלו את הקוד. בדקו באופן שיטתי (DevTools):
- (א) האם יש
container-type: inline-size? - (ב) האם יש
@containerולא@media? - (ג) האם יש
:has()? - (ד) האם צבעים ב-
oklch()? - (ה) האם יש
@layer? - (ו) האם nesting native עם
&?
- (א) האם יש
- אם אחת לא עברה — זהו את החלק בפרומפט שצריך חיזוק, והוסיפו ב-v1.1.
- בדקו ב-3 דפדפנים: Chrome, Safari 17+, Firefox. כולם צריכים לעבוד.
- אם יש Tier 2-3 — בדקו שה-fallback עובד (פתחו Chrome DevTools → Emulation → Safari 15).
מה צריך להיות בסוף: Component של product card עם 3 התנהגויות (sidebar/grid/featured), 6 תשובות לבדיקת DevTools, Modern CSS Prompt v1.1 אישי שלכם עם התיקונים, ו-screenshots של 3 הדפדפנים.
| תדירות | מה לעשות | כמה זמן |
|---|---|---|
| יומי | בקריאת קוד של פרויקט חדש (שלכם או בפרויקטים אחרים) — זהו מקום אחד שאפשר להחליף @media ל-@container, או מקום אחד של JS class-toggle שאפשר להחליף ל-:has(). לא חובה לבצע — רק לזהות ולכתוב למטה. |
3 דקות |
| שבועי | בנוסף לשגרה מפרק 5 (Layout Audit) — בדקו 1 אתר שאתם אוהבים ב-DevTools. חפשו שימוש ב-CSS מודרני. רשמו 2-3 דפוסים שראיתם. אם ראיתם פיצ'ר שלא מכירים — בדקו ב-caniuse.com. | 15 דקות |
| חודשי | עדכנו את Modern CSS Cheat Sheet שלכם: בדקו 5 פיצ'רים ב-Tier 3 וראו אם קודמו ל-Tier 2. עדכנו את התאריך last-verified. קראו את הבלוג של Bramus (bram.us/2024) ל-features חדשים. | 25 דקות |
הוסיפו את Modern CSS Prompt (section 6.18) לתחילת כל שיחה עם AI לבניית אתר. זו עבודה של העתקה והדבקה — פחות מדקה — והיא תגרום ל-AI להשתמש ב-Container Queries, :has(), @layer, oklch() ו-Popover API כברירת-מחדל במקום ב-CSS של 2015. ההבדל בתוצאה הוא בין אתר שנראה "AI" לאתר שנראה "בנוי ב-2026 על-ידי מישהו שיודע". אם רק תוסיפו את הפרומפט הזה לכל פרויקט — זכיתם בפרק.
- למה Container Queries לא מחליפות media queries, אלא משלימות אותן? תנו דוגמה לכל אחת. (רמז: רמת הדף vs רמת רכיב; navbar vs card)
- מה 3 השימושים הכי מעשיים של
:has()בפרויקט אמיתי? מדוע כל אחד מהם יותר טוב מ-JavaScript? (רמז: form validation, card states, empty states — state-from-HTML) - איך
@layerפותר specificity wars? למה utilities בשכבה מאוחרת גוברים על component בשכבה מוקדמת — גם אם ה-component עם specificity גבוה יותר? (רמז: layer ordering גובר על specificity) - באיזה Tier תשתמשו ב-Anchor Positioning באפריל 2026, ולמה חובה
@supports? מה הסיכון בלי? (רמז: Tier 2, Safari/Firefox בבנייה, tooltips שבורים) - למה
oklch()עדיף על HSL לבניית design system עם 5 רמות בהירות? תנו את ההבדל התפיסתי המרכזי. (רמז: perceptually uniform, צהוב ב-L=50 vs סגול ב-L=50)
בפרק הזה עברתם דרך שינוי תפיסה מהותי: CSS של 2024-2026 הוא לא CSS שאתם מכירים. הוא כלי הרבה חזק יותר, שיכול להחליף JavaScript ברוב המקרים שבהם השתמשתם בו עד היום. עברתם על 20 פיצ'רים חדשים, מחולקים ל-4 Tiers של תמיכה — Tier 1 (Stable: Container Queries, :has(), Nesting, @layer, color-mix(), oklch()), Tier 2 (Cutting-edge: Subgrid, @scope, Popover API, Anchor Positioning), Tier 3 (Emerging: Masonry, Mixins, sibling functions, corner-shape).
הבנתם ש-Container Queries הן המהפכה הגדולה — רכיבים שמגיבים לגודל הקונטיינר שלהם, לא ל-viewport. זה פותר את הבעיה הכי ישנה ב-responsive design: רכיב שמופיע ב-sidebar ו-main וצריך להתאים לשניהם. למדתם ש-:has() הוא ה-parent selector שחיכינו לו 20 שנה, ושהוא מאפשר להחליף עשרות שורות JavaScript ב-2-3 שורות CSS — form validation, card states, theme switching, empty states. למדתם ש-@layer פותר specificity wars אחת ולתמיד, ושדפוס 4-השכבות (tokens → base → components → utilities) הוא ה-architecture הסטנדרטי של CSS ב-2026.
קיבלתם כלים מעשיים: 4-Tier Decision Framework לבחירה באיזה פיצ'ר להשתמש, workflow של Can I Use ב-30 שניות לפני כל שימוש בפיצ'ר חדש, Template של @supports Progressive Enhancement שמבטיח שהאתר לא ישבר בדפדפנים ישנים, ו-Modern CSS Prompt ל-AI שמכריח אותו להשתמש בפיצ'רים מודרניים בשם ולא ב-"CSS מודרני" מעורפל.
בפרק הבא נבנה על הבסיס הזה. בפרק הבא נעבור ל-Scroll-Driven Animations — פיצ'ר CSS חדש שמאפשר אנימציות מבוססות גלילה (reveal, parallax, progress indicators) בלי JavaScript. הדפוס של @supports ו-progressive enhancement שלמדתם כאן יהיה קריטי שם — scroll-driven animations עדיין Tier 2-3 במרבית הדפדפנים, ואם לא תבנו אותם עם fallback תשברו את האתר ל-20% מהמשתמשים. פרק 6 הוא השער — בלי Container Queries, :has(), ו-@supports, פרק 7 לא יעבוד לכם. עם הכלים האלה — נהיה מוכנים להיכנס לעולם האנימציות של 2026.
- ☐ הבנתי את ההבדל בין
@containerל-@mediaומתי להשתמש בכל אחד - ☐ בדקתי
:has()support ב-caniuse.com ורשמתי את ה-Global percentage - ☐ בניתי component אחד שמשתמש ב-
container-type: inline-size+@container - ☐ כתבתי לפחות 3 שימושים של
:has()ב-CSS של הפרויקט שלי (form validation, card states, empty states) - ☐ המרתי לפחות רכיב אחד ל-CSS Nesting native עם אופרטור
& - ☐ הוספתי
@layer tokens, base, components, utilities;לקובץ ה-CSS שלי - ☐ הסרתי את כל מופעי
!importantמה-CSS אחרי מעבר ל-@layer - ☐ המרתי את פלטת הצבעים שלי ל-
oklch()(לפחות ה-primary palette) - ☐ השתמשתי ב-
color-mix()לייצור variant אחד לפחות (hover/light/dark) - ☐ בניתי לפחות modal/dropdown אחד עם Popover API במקום JavaScript
- ☐ יצרתי Modern CSS Cheat Sheet של 20 פיצ'רים עם תאריך last-verified
- ☐ כתבתי
@supportsblock אחד לפחות עבור Tier 2-3 feature - ☐ שמרתי את Modern CSS Prompt Template בקובץ נגיש ושילבתי עם פרומפטים קודמים
- ☐ הרצתי את הפרומפט בכלי AI ובדקתי 6 נקודות איכות (Container Queries,
:has(),oklch(),@layer, nesting, progressive enhancement)