|
| 1 | +--- |
| 2 | +name: modern-css |
| 3 | +description: | |
| 4 | + Modern CSS features and best practices for building interfaces with pure native CSS. |
| 5 | + Triggers on: CSS Grid, Subgrid, Flexbox, Container Queries, :has(), @layer, @scope, CSS nesting, |
| 6 | + @property, @function, if(), oklch, color-mix, light-dark, relative color, @starting-style, |
| 7 | + scroll-driven animations, view transitions, anchor positioning, popover, customizable select, |
| 8 | + content-visibility, logical properties, text-wrap, interpolate-size, clamp, field-sizing, |
| 9 | + modern CSS, CSS architecture, responsive design, dark mode, theming, design tokens, cascade layers. |
| 10 | +
|
| 11 | + Use when: writing CSS for any web project, choosing layout approaches, building responsive |
| 12 | + components, implementing dark mode or theming, creating animations or transitions, styling |
| 13 | + form elements, or modernizing legacy stylesheets. Proactively apply when creating design |
| 14 | + systems, component libraries, or any frontend application. |
| 15 | +--- |
| 16 | + |
| 17 | +# Modern CSS |
| 18 | + |
| 19 | +Pure native CSS for building interfaces — no preprocessors, no frameworks. |
| 20 | + |
| 21 | +## When to Use (and When NOT to) |
| 22 | + |
| 23 | +| Use Freely (Baseline) | Feature-Detect First | |
| 24 | +|---|---| |
| 25 | +| CSS Grid, Subgrid, Flexbox | `@function`, `if()` (Chrome-only) | |
| 26 | +| Container Queries (size + style) | Customizable `<select>` (Chrome-only) | |
| 27 | +| `:has()`, `:is()`, `:where()` | Scroll-state queries (Chrome-only) | |
| 28 | +| CSS Nesting, `@layer`, `@scope` | `sibling-index()`, `sibling-count()` | |
| 29 | +| `@property` (typed custom props) | `::scroll-button()`, `::scroll-marker` | |
| 30 | +| `oklch()`, `color-mix()`, `light-dark()` | Typed `attr()` beyond `content` | |
| 31 | +| Relative color syntax | `field-sizing: content` | |
| 32 | +| `@starting-style`, `transition-behavior` | `interpolate-size` (Chrome-only) | |
| 33 | +| Scroll-driven animations | Grid Lanes / masonry (experimental) | |
| 34 | +| Anchor positioning, Popover API | `random()` (Safari TP only) | |
| 35 | +| `text-wrap: balance`, `linear()` easing | `@mixin` / `@apply` (no browser yet) | |
| 36 | +| View Transitions, logical properties | | |
| 37 | + |
| 38 | +## CRITICAL: The Modern Cascade |
| 39 | + |
| 40 | +Understanding how styles resolve is the single most important concept in CSS. The additions of `@layer` and `@scope` fundamentally changed the cascade algorithm. |
| 41 | + |
| 42 | +``` |
| 43 | +Style Resolution Order (highest priority wins): |
| 44 | +┌─────────────────────────────────────────────────┐ |
| 45 | +│ 1. Transitions (active transition wins) │ |
| 46 | +│ 2. !important (user-agent > user > author) │ |
| 47 | +│ 3. @layer order (later layer > earlier layer) │ |
| 48 | +│ 4. Unlayered styles (beat ALL layers) │ |
| 49 | +│ 5. Specificity (ID > class > element) │ |
| 50 | +│ 6. @scope proximity (closer root wins) NEW │ |
| 51 | +│ 7. Source order (later > earlier) │ |
| 52 | +└─────────────────────────────────────────────────┘ |
| 53 | +
|
| 54 | +Unlayered > Last layer > ... > First layer |
| 55 | + (utilities) (reset) |
| 56 | +``` |
| 57 | + |
| 58 | +Cascade layers (`@layer`) and scope proximity (`@scope`) are now more powerful than selector specificity. Define your layer order once (`@layer reset, base, components, utilities;`) and specificity wars disappear. Unlayered styles always beat layered styles — use this for overrides. |
| 59 | + |
| 60 | +## Quick Decision Trees |
| 61 | + |
| 62 | +### "How do I lay this out?" |
| 63 | + |
| 64 | +``` |
| 65 | +Layout approach? |
| 66 | +├─ 2D grid (rows + columns) → CSS Grid |
| 67 | +│ ├─ Children must align across → Grid + Subgrid |
| 68 | +│ └─ Waterfall / masonry → grid-lanes (experimental) |
| 69 | +├─ 1D row OR column → Flexbox |
| 70 | +├─ Component adapts to container → Container Query + Grid/Flex |
| 71 | +├─ Viewport-based responsiveness → @media range syntax |
| 72 | +└─ Element sized to content → fit-content / min-content / stretch |
| 73 | +``` |
| 74 | + |
| 75 | +### "How do I style this state?" |
| 76 | + |
| 77 | +``` |
| 78 | +Style based on what? |
| 79 | +├─ Child/descendant presence → :has() |
| 80 | +├─ Container size → @container (inline-size) |
| 81 | +├─ Container custom property → @container style() |
| 82 | +├─ Scroll position (stuck/snapped) → scroll-state() query |
| 83 | +├─ Element's own custom property → if(style(...)) |
| 84 | +├─ Browser feature support → @supports |
| 85 | +├─ User preference (motion/color) → @media (prefers-*) |
| 86 | +└─ Multiple selectors efficiently → :is() / :where() |
| 87 | +``` |
| 88 | + |
| 89 | +### "How do I animate this?" |
| 90 | + |
| 91 | +``` |
| 92 | +Animation type? |
| 93 | +├─ Enter/appear on DOM → @starting-style + transition |
| 94 | +├─ Exit/disappear (display:none) → transition-behavior: allow-discrete |
| 95 | +├─ Animate to/from auto height → interpolate-size: allow-keywords |
| 96 | +├─ Scroll-linked (parallax/reveal) → animation-timeline: scroll()/view() |
| 97 | +├─ Page/view navigation → View Transitions API |
| 98 | +├─ Custom easing (bounce/spring) → linear() function |
| 99 | +└─ Always: respect user preference → @media (prefers-reduced-motion) |
| 100 | +``` |
| 101 | + |
| 102 | +## What CSS Replaced JavaScript For |
| 103 | + |
| 104 | +| JavaScript Pattern | CSS Replacement | |
| 105 | +|---|---| |
| 106 | +| Scroll position listeners | Scroll-driven animations | |
| 107 | +| IntersectionObserver for reveal | `animation-timeline: view()` | |
| 108 | +| Sticky header shadow toggle | `scroll-state(stuck: top)` | |
| 109 | +| Floating UI / Popper.js | Anchor positioning | |
| 110 | +| Carousel prev/next/dots | `::scroll-button()`, `::scroll-marker` | |
| 111 | +| Auto-expanding textarea | `field-sizing: content` | |
| 112 | +| Staggered animation delays | `sibling-index()` | |
| 113 | +| `max-height: 9999px` hack | `interpolate-size: allow-keywords` | |
| 114 | +| Parent element selection | `:has()` | |
| 115 | +| Theme toggle logic | `light-dark()` + `color-scheme` | |
| 116 | +| Tooltip/popover show/hide | Popover API + invoker commands | |
| 117 | +| Color manipulation functions | `color-mix()`, relative color syntax | |
| 118 | + |
| 119 | +> For non-Baseline features, always feature-detect with `@supports` or use progressive enhancement. Check [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) or [Baseline](https://web.dev/baseline) for current browser support. |
| 120 | +
|
| 121 | +## Anti-Patterns (CRITICAL) |
| 122 | + |
| 123 | +| Anti-Pattern | Problem | Fix | |
| 124 | +|---|---|---| |
| 125 | +| Overusing `!important` | Specificity arms race | Use `@layer` for cascade control | |
| 126 | +| Deep nesting (`.a .b .c .d`) | Fragile, DOM-coupled | Flat selectors, `@scope` | |
| 127 | +| IDs for styling (`#header`) | Too specific to override | Classes (`.header`) | |
| 128 | +| `@media` for component layout | Viewport-coupled, not reusable | Container queries | |
| 129 | +| JS scroll listeners for effects | Janky, expensive | Scroll-driven animations | |
| 130 | +| JS for tooltip positioning | Floating UI dependency | Anchor positioning | |
| 131 | +| JS for carousel controls | Fragile, a11y issues | `::scroll-button`, `::scroll-marker` | |
| 132 | +| JS for auto-expanding textarea | Unnecessary complexity | `field-sizing: content` | |
| 133 | +| `max-height: 9999px` for animation | Wrong duration, janky | `interpolate-size: allow-keywords` | |
| 134 | +| `margin-left` / `padding-right` | Breaks in RTL/vertical | Logical properties (`margin-inline-start`) | |
| 135 | +| `rgba()` with commas | Legacy syntax | `rgb(r g b / a)` space-separated | |
| 136 | +| `appearance: none` on selects | Removes ALL functionality | `appearance: base-select` | |
| 137 | +| Preprocessor-only variables | Can't change at runtime | CSS custom properties | |
| 138 | +| Preprocessor-only nesting | Extra build step dependency | Native CSS nesting | |
| 139 | +| Preprocessor color functions | Can't respond to context | `color-mix()`, relative colors | |
| 140 | +| `text-wrap: balance` on paragraphs | Performance-heavy | Only headings/short text | |
| 141 | +| `content-visibility` above fold | Delays LCP rendering | Only off-screen sections | |
| 142 | +| Overusing `will-change` | Wastes GPU memory | Apply only to animating elements | |
| 143 | + |
| 144 | +## Reference Documentation |
| 145 | + |
| 146 | +| File | Purpose | |
| 147 | +|------|---------| |
| 148 | +| [references/CASCADE.md](references/CASCADE.md) | Nesting, `@layer`, `@scope`, cascade control, and CSS architecture | |
| 149 | +| [references/LAYOUT.md](references/LAYOUT.md) | Grid, Subgrid, Flexbox, Container Queries, and intrinsic sizing | |
| 150 | +| [references/SELECTORS.md](references/SELECTORS.md) | `:has()`, `:is()`, `:where()`, pseudo-elements, and state-based selection | |
| 151 | +| [references/COLOR.md](references/COLOR.md) | OKLCH, `color-mix()`, relative colors, `light-dark()`, and theming | |
| 152 | +| [references/TOKENS.md](references/TOKENS.md) | `@property`, `@function`, `if()`, math functions, and design tokens | |
| 153 | +| [references/ANIMATION.md](references/ANIMATION.md) | `@starting-style`, `interpolate-size`, `linear()`, view transitions | |
| 154 | +| [references/SCROLL.md](references/SCROLL.md) | Scroll-driven animations, scroll-state queries, native carousels | |
| 155 | +| [references/COMPONENTS.md](references/COMPONENTS.md) | Customizable `<select>`, popover, anchor positioning, `field-sizing` | |
| 156 | +| [references/PERFORMANCE.md](references/PERFORMANCE.md) | `content-visibility`, typography, logical properties, accessibility | |
| 157 | +| [references/CHEATSHEET.md](references/CHEATSHEET.md) | Quick reference: browser support, legacy→modern patterns, units | |
| 158 | + |
| 159 | +## Sources |
| 160 | + |
| 161 | +### Official Specifications |
| 162 | +- [CSS Snapshot 2025](https://www.w3.org/TR/css-2025/) — W3C |
| 163 | +- [CSS Values and Units Level 5](https://www.w3.org/TR/css-values-5/) — `if()`, `random()`, `sibling-index/count()` |
| 164 | +- [CSS Functions and Mixins Level 1](https://www.w3.org/TR/css-mixins-1/) — `@function`, `@mixin` |
| 165 | +- [CSS Conditional Rules Level 5](https://www.w3.org/TR/css-conditional-5/) — Scroll-state queries |
| 166 | +- [CSS Anchor Positioning](https://www.w3.org/TR/css-anchor-position-1/) |
| 167 | +- [CSS Overflow Level 5](https://www.w3.org/TR/css-overflow-5/) — Scroll markers/buttons |
| 168 | + |
| 169 | +### Browser Vendor Blogs |
| 170 | +- [CSS Wrapped 2025](https://chrome.dev/css-wrapped-2025/) — Chrome DevRel |
| 171 | +- [Interop 2025](https://webkit.org/blog/17808/interop-2025-review/) — WebKit |
| 172 | +- [What's New in Web UI (I/O 2025)](https://developer.chrome.com/blog/new-in-web-ui-io-2025-recap) |
| 173 | + |
| 174 | +### Reference |
| 175 | +- [MDN Web Docs: CSS](https://developer.mozilla.org/en-US/docs/Web/CSS) |
| 176 | +- [State of CSS 2025](https://2025.stateofcss.com/en-US/features/) |
| 177 | +- [What You Need to Know About Modern CSS (2025)](https://frontendmasters.com/blog/what-you-need-to-know-about-modern-css-2025-edition/) |
| 178 | +- [CSS in 2026](https://blog.logrocket.com/css-in-2026/) |
0 commit comments