TocTable of Contents

Css baseline 2025

Overview of 2025 baseline css features

::details-content

The ::details-content pseudo-element targets the expandable content area of a <details> element — everything inside it except the <summary>. This gives you direct styling control over the hidden/shown region without needing a wrapper element.

Previously, styling the revealed content of a <details> element required wrapping everything in a <div> and targeting that. ::details-content removes that need, and more importantly, it enables smooth animations on the open/close transition — something that was not straightforward before because the content toggled between display: none and visible with no interpolatable state in between.

1
2
3
4
5
6
details::details-content {
  padding: 1rem;
  background: #f5f5f5;
  overflow: hidden;
  transition: height 0.3s ease, content-visibility 0.3s ease allow-discrete;
}

Combined with interpolate-size and transition-behavior, ::details-content makes it possible to animate the expanding and collapsing of <details> elements using only CSS, bringing native disclosure widgets in line with what previously required JavaScript.

@scope

The @scope at-rule allows you to apply styles scoped to a specific subtree of the DOM, defined by a scoping root and an optional scoping limit. Styles inside @scope only match elements within the defined scope, without the need for deeply nested selectors or BEM-style naming conventions.

1
2
3
4
5
6
7
8
9
@scope (.card) {
  p {
    font-size: 0.9rem;
  }

  img {
    border-radius: 4px;
  }
}

You can also define a lower boundary to exclude nested components from the scope:

1
2
3
4
5
@scope (.card) to (.card__footer) {
  a {
    color: var(--card-link-color);
  }
}

In this example, the a rule applies to links inside .card but not to any links inside .card__footer. This makes it straightforward to style a component without accidentally affecting nested components of the same type, solving a long-standing problem with CSS specificity and inheritance that previously required either strict naming conventions or JavaScript-based scoping solutions like CSS Modules or Shadow DOM.

Inside a @scope block, the :scope pseudo-class refers to the scoping root element itself, giving you a convenient way to style the root of the component directly.

abs() and sign()

abs() and sign() are CSS math functions that extend the toolkit available inside calc() and other math contexts.

abs() returns the absolute value of its argument — always a non-negative number, regardless of whether the input is positive or negative. This is useful when you need to work with the magnitude of a value without knowing its sign in advance.

1
2
3
4
.element {
  /* Ensures the offset is always positive */
  margin-top: abs(var(--offset));
}

sign() returns -1, 0, or 1 depending on whether its argument is negative, zero, or positive. Combined with multiplication, this lets you flip or preserve the direction of a value conditionally in pure CSS math.

1
2
3
4
.element {
  /* Move left if offset is negative, right if positive */
  translate: calc(sign(var(--offset)) * 10px) 0;
}

Both functions are particularly valuable in combination with CSS custom properties and other math functions like clamp() and round(), enabling more expressive layout logic without JavaScript.

content-visibility

The content-visibility property allows the browser to skip rendering work for elements that are not currently visible in the viewport. Setting it to auto tells the browser it can defer layout, paint, and compositing for off-screen elements, resuming that work only when they are about to scroll into view.

This can produce significant performance improvements on long pages with many elements, as the browser does far less work on initial load and during scrolling.

1
2
3
4
.article-card {
  content-visibility: auto;
  contain-intrinsic-size: auto 300px;
}

The contain-intrinsic-size property accompanies content-visibility: auto to give the browser a placeholder size for the element while its content is not rendered. Without it, all off-screen elements would collapse to zero height, causing layout jumps as they scroll into view.

content-visibility: hidden is a stricter variant that keeps the element’s rendering state cached but always hidden — similar to display: none in visibility but preserving the rendered state for fast unhiding. content-visibility: visible is the default, applying no skipping behaviour.