16 features ← 2026

What's New in CSS 2025

A timeline of CSS features that shipped in browsers in 2025. Customizable selects, invoker commands, CSS functions, scroll-state queries, and much more.

Customizable Select

Layout

Fully style HTML select dropdowns with appearance: base-select. The dropdown renders in the top layer, supports rich HTML in options, and the new selectedcontent element reflects the chosen option.

Example
select {
  appearance: base-select;
}

select::picker(select) {
  background: #1a1a2e;
  border: 1px solid #333;
  border-radius: 12px;
  padding: 8px;
}
💡
Use case

Build fully branded select dropdowns without JavaScript libraries like Select2 or Choices.js. Style the button, picker, options, and selected content with standard CSS.

Status Working Draft
Shipped Chrome 134
Browsers Chrome Edge Firefox Safari
Spec CSS Basic User Interface Level 4

Invoker Commands

Layout

Buttons can now perform actions on other elements declaratively with commandfor and command attributes. Open modals, toggle popovers, and close dialogs without JavaScript.

Example
<button commandfor="my-dialog" command="show-modal">
  Open Dialog
</button>

<dialog id="my-dialog">
  <p>Hello!</p>
  <button commandfor="my-dialog" command="close">
    Close
  </button>
</dialog>
💡
Use case

Wire up interactive UI — modals, popovers, toggle panels — with HTML attributes alone. No addEventListener, no onclick handlers, no framework needed.

Status Explainer
Shipped Chrome 135
Browsers Chrome Edge Firefox Safari
Spec Invoker Commands

Dialog Light Dismiss

Layout

The closedby attribute brings popover-style light dismiss to dialogs. Set closedby="any" to close on backdrop click or ESC, or closedby="closerequest" for ESC only.

Example
<!-- Close on backdrop click or ESC -->
<dialog closedby="any">
  <p>Click outside to close</p>
</dialog>

<!-- Close on ESC only -->
<dialog closedby="closerequest">
  <p>Press ESC to close</p>
</dialog>
💡
Use case

Eliminate click-outside event listeners for modal dismissal. The closedby attribute handles backdrop clicks and keyboard dismiss natively.

Status Living Standard
Shipped Chrome 134
Browsers Chrome Edge Firefox Safari
Spec HTML Dialog Element

popover=hint & Interest Invokers

Layout

Hint popovers are ephemeral and don't close other popovers. The interestfor attribute triggers them on hover/focus declaratively. Perfect for tooltips and hovercards.

Example
<button interestfor="my-tip">
  Hover me
</button>

<div id="my-tip" popover="hint">
  This is a tooltip!
</div>
💡
Use case

Build tooltips and hovercards that appear on hover/focus without JavaScript mouseenter/mouseleave event listeners. Hint popovers coexist with other open popovers.

Status Living Standard
Shipped Chrome 135
Browsers Chrome Edge
Spec Popover API — Hint

Scroll-State Container Queries

Animation

Style descendants based on whether a scroll container is stuck, snapped, or scrollable. Use container-type: scroll-state with @container scroll-state() queries.

Example
.sticky-header {
  position: sticky;
  top: 0;
  container-type: scroll-state;
}

@container scroll-state(stuck: top) {
  .sticky-header {
    box-shadow: 0 2px 8px rgba(0,0,0,.15);
    backdrop-filter: blur(12px);
  }
}
💡
Use case

Add shadow to a sticky header when it sticks, highlight a snapped carousel slide, or show scroll indicators when a container is scrollable — all without JavaScript scroll listeners.

Status Editor's Draft
Shipped Chrome 133
Browsers Chrome Edge
Spec CSS Conditional Rules Level 5

Tree Counting Functions

Animation

sibling-index() returns an element's position among siblings; sibling-count() returns the total. Ideal for staggered animations and dynamic layouts without manual indexing.

Example
.card {
  animation-delay: calc(sibling-index() * 80ms);
  opacity: 0;
  animation: fade-in 0.4s forwards;
}

.item {
  flex-basis: calc(100% / sibling-count());
}
💡
Use case

Create staggered entrance animations and equal-width flex layouts without nth-child hacks or custom properties on every element. The functions update dynamically when items are added or removed.

Status Working Draft
Shipped Chrome 136
Browsers Chrome Edge
Spec CSS Values and Units Level 5

CSS Scroll Markers & Buttons

Layout

Build carousels with CSS-only pseudo-elements. ::scroll-button() creates navigation arrows, ::scroll-marker creates dot indicators. Both are accessible and stylable.

Example
.carousel {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
}

.carousel::scroll-button(left) {
  content: '←';
}
.carousel::scroll-button(right) {
  content: '→';
}

.carousel > * {
  scroll-snap-align: center;
}
.carousel > *::scroll-marker {
  content: '';
  border-radius: 50%;
  width: 10px; height: 10px;
  background: gray;
}
💡
Use case

Build accessible carousels with prev/next buttons and dot indicators using only CSS. No Swiper.js, no Flickity, no JavaScript event wiring needed.

Status Editor's Draft
Shipped Chrome 135
Browsers Chrome Edge Firefox Safari
Spec CSS Overflow Level 5

text-box (trim & edge)

Typography

Trim invisible font metric space for true optical centering. text-box: trim-both cap alphabetic removes ascent/descent padding so text is visually centered in buttons, badges, and headings.

Example
.button {
  text-box: trim-both cap alphabetic;
  /* shorthand for:
     text-box-trim: trim-both;
     text-box-edge: cap alphabetic; */
}

h1 {
  text-box: trim-both cap alphabetic;
  /* text sits flush — no phantom spacing */
}
💡
Use case

Vertically center text in buttons, badges, and pill labels without padding hacks. Align headings flush to their container edge without invisible font metric space.

Status Working Draft
Shipped Chrome 133, Safari 18.2
Browsers Chrome Safari Edge Firefox
Spec CSS Inline Layout Level 3

CSS if() Function

Workflow

Conditional values in CSS properties. Use if(media(...): value; else: fallback) for inline media queries, if(supports(...): ...) for feature queries, and if(style(...): ...) for style queries.

Example
.container {
  padding: if(
    media(width >= 768px): 40px;
    else: 16px
  );

  display: if(
    supports(display: grid): grid;
    else: flex
  );
}
💡
Use case

Write conditional property values inline without separate @media or @supports blocks. Ideal for one-off responsive adjustments and progressive enhancement directly in declarations.

Status Working Draft
Shipped Chrome 137
Browsers Chrome Edge
Spec CSS Values and Units Level 5

CSS Custom Functions (@function)

Workflow

Define reusable functions with @function --name(args) { @return ... }. Write composable, maintainable CSS logic like conditional border-radius, clamped values, and utility helpers.

Example
@function --fluid-size(--min, --max) {
  @return clamp(
    var(--min),
    var(--min) + (var(--max) - var(--min)) * 
      (100vw - 320px) / (1200 - 320),
    var(--max)
  );
}

h1 { font-size: --fluid-size(1.5rem, 3rem); }
💡
Use case

Replace Sass functions with native CSS. Build reusable utility functions for fluid sizing, conditional radius, spacing scales, and color manipulation — no build step required.

Status Editor's Draft
Shipped Chrome 137
Browsers Chrome Edge
Spec CSS Functions and Mixins

Advanced attr() Function

Workflow

attr() now works beyond content property and can parse values as typed data: colors, lengths, numbers, and custom identifiers. Use with any CSS property.

Example
<div data-color="#7c3aed" data-size="200">

.box {
  background: attr(data-color type(<color>));
  width: attr(data-size type(<length>), 100px);
  /* typed parsing with fallback */
}
💡
Use case

Drive CSS property values from HTML data attributes without JavaScript. Set colors, sizes, delays, and any typed value directly from markup for data-driven components.

Status Working Draft
Shipped Chrome 133
Browsers Chrome Edge
Spec CSS Values and Units Level 5

shape() Function

Animation

Create complex, responsive clip paths with the shape() function. Supports curves, lines, and CSS custom properties for dynamic clipping that scales with element size.

Example
.blob {
  clip-path: shape(
    from 0% 50%,
    curve to 50% 0% with 0% 0%,
    curve to 100% 50% with 100% 0%,
    curve to 50% 100% with 100% 100%,
    curve to 0% 50% with 0% 100%
  );
}
💡
Use case

Build complex, responsive clip paths that use percentages and custom properties instead of fixed SVG coordinates. Create blobs, waves, notches, and organic shapes that scale with element size.

Status Editor's Draft
Shipped Chrome 137
Browsers Chrome Edge
Spec CSS Shapes Level 2

stretch Sizing Keyword

Layout

Make elements fill their containing block with width: stretch or height: stretch. Unlike 100%, it applies to the margin box so margins are respected without calc() hacks.

Example
.full-width {
  width: stretch;
  margin-inline: 24px;
  /* fills container minus margins — 
     no calc(100% - 48px) needed */
}

.full-height {
  height: stretch;
}
💡
Use case

Make elements fill available space while respecting their margins. Replaces calc(100% - margins) patterns and -webkit-fill-available hacks with a single standardized keyword.

Status Editor's Draft
Shipped Baseline 2025
Browsers Chrome Firefox Safari Edge
Spec CSS Box Sizing Level 4

corner-shape Property

Layout

Go beyond border-radius with corner-shape: round, bevel, notch, scoop, or squircle. Create flower shapes, hexagonal grids, and iOS-style squircles in pure CSS.

Example
.squircle {
  border-radius: 24px;
  corner-shape: squircle;
}

.notched {
  border-radius: 16px;
  corner-shape: notch;
}

.scooped {
  border-radius: 40px;
  corner-shape: scoop;
}
💡
Use case

Create iOS-style squircle icons, beveled card corners, scooped photo frames, and notched UI elements without SVG clip-path hacks.

Status Editor's Draft
Shipped Chrome 142
Browsers Chrome Edge
Spec CSS Backgrounds and Borders Level 4

Anchored Container Queries

Layout

Style elements based on their anchor positioning fallback. Use @container anchored(fallback: flip-block) to flip tooltip arrows automatically when position changes.

Example
.tooltip {
  position: absolute;
  position-anchor: --trigger;
  position-area: top;
  position-try-fallbacks: flip-block;
}

@container anchored(fallback: flip-block) {
  .tooltip::after {
    /* flip arrow direction */
    transform: rotate(180deg);
  }
}
💡
Use case

Automatically flip tooltip arrows, dropdown carets, and popover indicators when anchor positioning triggers a fallback. No JavaScript resize or position observers needed.

Status Working Draft
Shipped Chrome 138
Browsers Chrome Edge
Spec CSS Anchor Positioning Level 1

Nested View Transition Groups

Animation

Retain 3D and clipping effects during view transitions by nesting ::view-transition-group pseudo-elements. Use view-transition-group: nearest on child elements.

Example
.card {
  view-transition-name: card;
}

.card-image {
  view-transition-name: card-img;
  view-transition-group: nearest;
  /* nests under ::view-transition-group(card) 
     instead of the root group */
}
💡
Use case

Keep child elements clipped and transformed relative to their parent during view transitions. Cards with images, headers with logos, and nested layouts maintain spatial relationships.

Status Working Draft
Shipped Chrome 136
Browsers Chrome Edge
Spec CSS View Transitions Level 2
ESC