CSS Highlights – 2024


1. Popover API & Anchor positioning


The Popover API provides a native, accessible way to show floating UI (menus, tooltips, dialogs) without JavaScript libraries.


Basic usage

<button popovertarget="menu">Open menu</button>

<div id="menu" popover>
  Menu content
</div>

The browser handles:

  • opening / closing
  • focus management
  • Escape key
  • click-outside dismissal

Key features

  • No JS required for basic behavior
  • Built-in accessibility
  • Works well with keyboard & screen readers

Styling a popover

[popover] {
  padding: 1rem;
  border-radius: 8px;
}

Popover types

  • popover="auto" (default): dismisses on outside click
  • popover="manual": fully controlled by JS
  • Because a popover has no positioning instructions, the browser uses a safe, default placement: centered in the viewport unless specified otherwise

Anchor Positioning

What it is (one sentence)

Anchor positioning lets you position an element relative to another element in pure CSS, without JavaScript calculations.


Basic example

<button id="btn">Info</button>

<div popover anchor="btn">
  Tooltip text
</div>
[popover] {
  position-anchor: --btn;
  position: absolute;
  inset-area: bottom;
}

The popover stays attached even if layout changes.


Why this matters

Before:

  • JS measured positions
  • window resize listeners
  • fragile calculations

Now:

  • CSS handles alignment
  • responds to layout automatically
  • less JS, more reliability

Why they’re often paired

Popover handles:

  • visibility
  • focus
  • dismissal

Anchor positioning handles:

  • where it appears
  • how it tracks its anchor

Together they replace many tooltip / dropdown libraries.


2. Scroll driven animations


Scroll-driven animations let CSS animations progress based on scroll position instead of time.


The problem they solve

Traditionally:

  • scroll animations → JavaScript scroll listeners
  • poor performance
  • hard to sync with layout

Scroll-driven animations move this into the browser’s rendering engine.


Core concepts

1️⃣ Scroll timelines

scroll timeline maps scroll progress → animation progress.

@scroll-timeline scroll-progress {
  source: auto;
}

(New syntax is evolving)


2️⃣ animation-timeline

.box {
  animation: fade-in linear;
  animation-timeline: scroll();
}

The animation advances as you scroll.


3️⃣ View timelines (element-based)

.card {
  animation: slide-in linear;
  animation-timeline: view();
}

The animation runs as the element enters and leaves the viewport.


Why this is a big deal

  • compositor-driven (very smooth)
  • browser understands layout + scroll
  • espects prefers-reduced-motion
  • no JS math or listeners

Typical use cases

  • progress bars
  • parallax effects
  • fade/slide on enter
  • storytelling layouts
  • section reveals

3. New color functions



Modern CSS color functions let you define colors in perceptual color spaces, making color adjustments more predictable, accessible, and design-friendly.

Why new color functions were needed

Older formats (rgb()hex) are:

  • device-based
  • not perceptually uniform
  • hard to adjust logically (lighten, darken, mix)

New functions fix this.


Key modern CSS color functions

🎨 lab()

color: lab(60% 40 30);
  • Based on CIELAB, a perceptual color space
  • Changes to lightness behave how humans expect
  • Great for accessible color systems

Mental model:

“If I increase lightness, it actually looks lighter.”


lch()

color: lch(60% 70 40);
  • Lightness, Chroma, Hue
  • Easier for designers than LAB
  • Ideal for gradients and themes

Very popular for design systems


oklab() & oklch()

color: oklch(65% 0.15 240);
  • Improved perceptual accuracy over LAB/LCH
  • Better hue consistency
  • Increasingly recommended for modern work

Best choice today for color systems.


color-mix()

color: color-mix(in oklch, red 40%, blue);
  • Mixes colors in a chosen color space
  • Predictable results
  • Great for hover states and themes

color()

color: color(display-p3 1 0.5 0);
  • Access to wide-gamut color spaces
  • Supports Display-P3, Rec2020, etc.
  • Enables richer colors on modern displays

relative-color() (emerging)

color: relative-color(currentColor lch l +10%);
  • Adjusts a color relative to another
  • Ideal for hover / active states
  • Still evolving support

Why this matters in real projects

  • Better contrast control
  • More consistent themes
  • Easier dark mode
  • Fewer magic numbers

4. @property (custom properties)


@property lets you register a CSS custom property with a type, initial value, and inheritance behavior, so the browser can understand and animate it properly.


The problem it solves

Normal CSS variables (--x) are:

  • just strings
  • not type-aware
  • not animatable in a meaningful way
/* This cannot animate smoothly */
.box {
  --angle: 0deg;
}

The browser doesn’t know 0deg → 360deg is an angle.


What @property adds

When you register a property, you tell the browser:

  • what type it is
  • whether it inherits
  • its initial value
@property --angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

Now the browser understands --angle as an angle.


Why this matters (key benefits)

✅ Smooth animations

.box {
  animation: spin 2s linear infinite;
}

@keyframes spin {
  to {
    --angle: 360deg;
  }
}

Without @property, this would jump, not animate.


✅ Type safety

syntax: "<number>" | "<length>" | "<color>" | "<angle>";

Invalid values are rejected early.


✅ Better performance

  • Browser can animate on the compositor
  • No JS required

Common use cases

  • animated gradients
  • rotating elements
  • progress indicators
  • scroll-driven animations
  • theme transitions

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *