# Modern CSS Features (2023–2025) — Deep Dive

> Powerful, under-the-radar CSS features that many developers haven't adopted yet.

---

## 1. CSS Nesting (Native, 2024+)

Built-in nesting — no preprocessor needed.

```css
.card {
  padding: 1rem;
  border-radius: 8px;

  &__title {
    font-size: 1.5rem;

    &:hover {
      text-decoration: underline;
    }
  }

  &__body {
    color: #555;
  }

  /* Nested media queries */
  @media (min-width: 768px) {
    padding: 2rem;
    font-size: 1.25rem;
  }
}
```

> **Support:** Chrome 120+, Safari 16.6+, Firefox 128+

---

## 2. `:has()` — The "Parent Selector"

Match elements based on their descendants.

```css
/* Style a card containing an image */
article:has(> img) { border: 2px solid #0af; }

/* Style fieldset when input is focused */
fieldset:has(input:focus) {
  border-color: #0066ff;
  box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.15);
}

/* Form validation — disable submit if invalid */
form:has(input:invalid) .submit-btn {
  opacity: 0.5;
  pointer-events: none;
}

/* No-children pattern */
.section:not(:has(*)) { display: none; }
```

> **Support:** Chrome 105+, Safari 15.4+, Firefox 121+

---

## 3. CSS Custom Properties Deep Dive

### Inheritance

```css
:root {
  --brand-hue: 210;
  --brand-saturation: 80%;
  --brand-lightness: 55%;
}

.card {
  --brand-lightness: 70%;  /* Override for subtree */
}

.card__header {
  background: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}
```

### `@property` — Typed Custom Properties (No Safari)

```css
@property --progress {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}

@property --hue {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

/* Now animatable! */
.progress-bar { animation: load 2s linear forwards; }
@keyframes load { to { --progress: 100%; } }

@keyframes hue-cycle { to { --hue: 360; } }
.rainbow {
  background: hsl(var(--hue), 70%, 60%);
  animation: hue-cycle 5s linear infinite;
}
```

### Fallback Chain

```css
.color {
  color: var(--primary, var(--secondary, blue));
}
```

---

## 4. CSS Color Functions

### `color-mix()` — Mix Two Colors

```css
.button {
  background: color-mix(in srgb, red 80%, blue);
  background: color-mix(in hsl, #3498db, #e74c3c 30%);
  background: color-mix(in srgb, #2196f3, transparent 50%);
}
```

### `oklch()` — Perceptually Uniform Color Space

```css
:root {
  --brand: oklch(70% 0.15 220);   /* Lightness, Chroma, Hue */
  --text:  oklch(20% 0.01 220);
}

/* Seamless lightness-only gradient */
.palette {
  background: linear-gradient(
    to right,
    oklch(95% 0.1 200),
    oklch(85% 0.1 200),
    oklch(75% 0.1 200),
    oklch(65% 0.1 200),
    oklch(55% 0.1 200),
    oklch(45% 0.1 200)
  );
}
```

### Relative Notation — `rgb(from ...)`

```css
:root { --original: rgb(100 150 200); }

.element {
  color: rgb(from var(--original) r + 20 g b);
  background: rgb(from var(--original) calc(255 - r) g b);
}

/* Works with oklch too */
.element {
  color: oklch(from var(--original) calc(L + 0.1) C calc(H + 10));
}
```

### `color-contrast()` — Auto Accessibility

```css
.dynamic-card {
  --bg: oklch(80% 0.2 180);
  color: color-contrast(var(--bg) vs white, black, #333);
}
```

> **Support (color-mix, oklch, relative notation):** Chrome 119+, Safari 17+, Firefox 128+

---

## 5. CSS Animations

### Scroll-Driven Animations

```css
/* Hero fades as you scroll */
.hero {
  animation: fade-out linear;
  animation-timeline: scroll();
}
@keyframes fade-out {
  to { opacity: 0; transform: scale(0.8); }
}

/* Progress bar fills as you scroll */
.scroll-progress {
  position: fixed;
  top: 0; left: 0;
  height: 4px;
  background: #3498db;
  animation: progress linear;
  animation-timeline: scroll(root);
}
@keyframes progress { to { width: 100%; } }

/* Animate when element enters viewport */
.card {
  animation: slide-up linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 40%;
}
@keyframes slide-up {
  from { opacity: 0; transform: translateY(100px); }
  to   { opacity: 1; transform: translateY(0); }
}
```

### View Transitions

```css
.photo-card { view-transition-name: photo-card; }

::view-transition-old(root) { animation: fade-out 0.3s ease-in; }
::view-transition-new(root) { animation: fade-in 0.3s ease-out; }
```

---

## 6. CSS Layers (`@layer`)

Control cascade priority without `!important`.

```css
/* First declared = lowest priority */
@layer reset, base, components, utilities;

@layer reset {
  * { margin: 0; padding: 0; box-sizing: border-box; }
}

@layer base {
  body { font-family: system-ui, sans-serif; }
}

@layer components {
  .card { padding: 1.5rem; border-radius: 8px; }
}

@layer utilities {
  .mt-2 { margin-top: 0.5rem; }
}

/* Import framework at lowest priority */
@layer framework { @import "tailwind.css"; }
```

---

## 7. Advanced Selectors

### `:is()` — Forgiving Selector List

```css
:is(h1, h2, h3) { font-weight: 700; }
:is(article, section) :is(h1, h2) { color: var(--heading-color); }
```

### `:where()` — Zero Specificity

```css
:where(h1, h2, h3, h4, h5, h6) { margin: 0; }
:where(button, input, textarea, select) { font-family: inherit; }
```

### `:not()` — Multiple Selectors

```css
li:not(:first-child, :last-child) { border-top: 1px solid #eee; }
.card:not(:has(.featured-badge)) { opacity: 0.7; }
```

### Advanced `:nth-child()`

```css
li:nth-child(3n + 2) { color: red; }      /* Every 3rd starting from 2nd */
li:nth-last-child(3) { background: yellow; }
```

---

## 8. CSS Logical Properties

Map physical properties to logical directions — automatic RTL/writing-mode support.

```css
.card {
  margin-block: 1rem;        /* replaces margin-top/bottom */
  margin-inline: 2rem;       /* replaces margin-left/right */
  padding-block-start: 0.5rem;
  padding-inline: 1.5rem;

  border-start-start-radius: 8px;  /* border-top-left */
  border-end-end-radius: 8px;      /* border-bottom-right */

  inset-block-start: 0;    /* replaces top */
  inset-inline-start: 1rem; /* replaces left */

  block-size: 200px;       /* replaces height */
  inline-size: 300px;      /* replaces width */
}

/* Writing mode */
.vertical-text {
  writing-mode: vertical-rl;
  margin-block: 2rem;
  padding-inline: 1rem;
}
```

---

## 9. CSS Scroll Snap

Native carousels without JavaScript.

```css
.carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
}

.carousel__slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
}

/* Center snap */
.gallery {
  scroll-snap-type: x mandatory;
  padding-inline: 10%;
}
.gallery__item {
  scroll-snap-align: center;
  scroll-snap-stop: always;  /* Never skip items */
}
```

---

## 10. CSS `@scope` (2024+)

Scoped styles without Shadow DOM.

```css
@scope (.sidebar) to (.sidebar__content) {
  h2 { color: blue; font-size: 1.2rem; }  /* Only inside .sidebar */
  a { color: purple; }
  p { font-size: 0.9rem; }
}

h2 { color: black; font-size: 2rem; }  /* Global, not affected */

/* Component isolation */
@scope (.modal) {
  button {
    background: #0066ff;
    color: white;
    border: none;
  }
}
```

> **Support:** Chrome 125+, Safari 18+

---

## 11. Text Features

```css
/* Balance heading lines */
h1, h2, h3 { text-wrap: balance; }

/* Prevent widows (single word on last line) */
p { text-wrap: pretty; }

/* Prevent iOS font scaling */
html { text-size-adjust: none; }

/* Break long words */
.code { overflow-wrap: break-word; word-break: break-all; }

/* Automatic hyphenation */
article { hyphens: auto; }
```

---

## 12. `@starting-style` — Entry Animations

```css
.modal {
  opacity: 0;
  transition: opacity 0.3s ease;
}
.modal.is-open { opacity: 1; }

@starting-style {
  .modal.is-open { opacity: 0; }  /* Starting state for first render */
}

/* Slide-in notification */
.toast {
  transform: translateX(100%);
  transition: transform 0.3s ease-out;
}
.toast.visible { transform: translateX(0); }

@starting-style {
  .toast.visible { transform: translateX(100%); }
}
```

> **Support:** Chrome 118+, Edge 118+

---

## 13. `accent-color` — Restyle Form Controls

```css
:root { accent-color: #6366f1; }

input[type="checkbox"] { accent-color: #10b981; }
input[type="radio"] { accent-color: #f43f5e; }
input[type="range"] { accent-color: #8b5cf6; }
progress { accent-color: #06b6d4; }
```

---

## 14. `color-scheme` — Automatic Dark Mode

```css
:root { color-scheme: light dark; }

/* Browser auto-styles form controls, scrollbars, cursor */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a2e;
    --text: #e0e0e0;
  }
}

::selection { background: #0066ff; color: white; }
@media (prefers-color-scheme: dark) {
  ::selection { background: #6366f1; color: white; }
}
```

---

## Browser Support Matrix (2025)

| Feature | Chrome | Firefox | Safari |
|---------|--------|---------|--------|
| CSS Nesting | ✅ 120+ | ✅ 128+ | ✅ 16.6+ |
| `:has()` | ✅ 105+ | ✅ 121+ | ✅ 15.4+ |
| `@property` | ✅ 85+ | ✅ 128+ | ❌ |
| `color-mix()` | ✅ 119+ | ✅ 128+ | ✅ 17+ |
| `oklch()` | ✅ 119+ | ✅ 128+ | ✅ 17+ |
| Scroll-driven anims | ✅ 115+ | ✅ 128+ | ❌ |
| View transitions | ✅ 111+ | ✅ 128+ | ❌ |
| `@layer` | ✅ 99+ | ✅ 97+ | ✅ 16+ |
| `@scope` | ✅ 125+ | ❌ | ✅ 18+ |
| `text-wrap: balance` | ✅ 117+ | ✅ 128+ | ✅ 17.2+ |
| `@starting-style` | ✅ 118+ | ❌ | ❌ |
| `accent-color` | ✅ 93+ | ✅ 127+ | ✅ 16.4+ |
| Logical properties | ✅ 87+ | ✅ 114+ | ✅ 15.4+ |
| Scroll snap | ✅ 69+ | ✅ 68+ | ✅ 15+ |
