What's new in web UI

Published: July 1, 2026

At Google I/O 2026, we shared a whirlwind of updates landing in the Web UI platform. From respecting user preferences to implementing natural interactions, guiding navigation, reducing clutter, and adapting to various form factors, the modern web offers developers incredibly powerful tools to build high-quality, tactile user experiences.

Here is a comprehensive round-up of all the features mentioned in the "What's new in web UI" session, structured by our core set of UX principles.

Part 1: Respect user preferences

Personalization is fundamental for web usability. Modern web APIs make it easier to adapt to user system-level choices automatically. Even though these concepts feel elemental and we've been talking about them for years, there are actually a few new APIs and patterns that make this dynamic personalization easier to build for.

1. contrast-color()

The contrast-color() CSS function takes an input color and automatically returns either black or white, depending on which has the higher contrast against the input color based on the WCAG AA minimum contrast algorithm. This ensures legibility without manually maintaining text-background color pairs.

Browser Support

  • Chrome: 147.
  • Edge: 147.
  • Firefox: 146.
  • Safari: 26.

Source

Learn more about contrast-color()

2. light-dark()

The light-dark() CSS function lets you specify two different values (colors or images) for a property, one for light mode and one for dark mode, within a single declaration. The browser automatically selects the correct contrast color based on the active color-scheme (which must be set to light, dark, or light dark on :root or a parent).

Browser Support

  • Chrome: 123.
  • Edge: 123.
  • Firefox: 120.
  • Safari: 17.5.

Source

New to light-dark() is that it is no longer limited to just color values. Starting with Chrome 150, it now also accepts two image values.

Browser Support

  • Chrome: behind a flag.
  • Edge: behind a flag.
  • Firefox: 150.
  • Safari: not supported.

3. CSS custom functions (@function)

The @function at-rule lets you define custom, reusable functions directly within native CSS. It can accept locally-scoped custom properties as arguments, perform calculations, and return values using the result descriptor, reducing the need for preprocessors.

Browser Support

  • Chrome: 139.
  • Edge: 139.
  • Firefox: not supported.
  • Safari: not supported.

Source

Combined with container style queries and the CSS if() function, you can create a custom --light-dark() function that works with any type of value, as shown in this demo:

4. Container style queries

Part of CSS Container Queries, style queries let developers apply styles to descendant elements based on the computed custom property values of a parent container, enabling dynamic components without requiring explicit size containment.

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 151.
  • Safari: 18.

In this demo, style queries are used to set the colors based on a --theme custom property.

@container style(--theme: primary) {
  .app-card {
    --bg-light: #fdf2f8; 
    --bg-dark: #ff91d3;  
    --neon-glow: #f472b6;
    --btn-light: #be185d; 
    --btn-dark: #fbcfe8;  
    
    --text-on-light: #500732;
    --text-on-dark: #fff1f2;  
  }
}

@container style(--theme: accent) {
  .app-card {
    --bg-light: #f3e8ff;
    --bg-dark: #4c1d95;  
    --neon-glow: #d8b4fe;
    --btn-light: #7e22ce; 
    --btn-dark: #c084fc;  
    
    --text-on-light: #2e1065; 
    --text-on-dark: #faf5ff;  
  }
}

@container style(--theme: success) {
  /* … */
}

Learn more about style queries

5. CSS if() function

The if() CSS function brings inline conditional logic directly to CSS property values. It evaluates a series of semicolon-separated conditions (style queries, media queries, or feature queries) and lets you set different values associated with the first true condition, with an optional else fallback.

Browser Support

  • Chrome: 137.
  • Edge: 137.
  • Firefox: not supported.
  • Safari: not supported.

Source

In the previous demo, the if() function is used to create a themed contrast color base on the output of the contrast-color() function.

--contrast-color: contrast-color(var(--card-bg));
color: if(
    style(--contrast-color: white): var(--text-on-dark);
    else: var(--text-on-light)
);

6. @supports at-rule()

The CSS at-rule() function for use with @supports allows developers to feature-detect whether a browser recognizes a specific at-rule, such as @starting-style or @view-transition.

For example, to check for support for @function, use it as follows:

@supports at-rule(@function) {
  /* Code for browsers that support @function goes here */
}

Using at-rule() only allows checking for base support of the at-rule itself and cannot be used to test for specific descriptors, preludes, or full at-rule blocks. There are workarounds available to feature detect things like anchored queries or style queries.

Learn more about @supports at-rule

7. <meta name="text-scale">

The text-scale HTML meta tag opts the page in to having the <html> root element's initial font size scale in proportion to OS and browser-level text scale settings, which is especially critical for mobile platforms.

Browser Support

  • Chrome: 146.
  • Edge: 146.
  • Firefox: not supported.
  • Safari: not supported.

Source

When applied, the font-size on the html element is now determined by the operating system, so there is no need for you to set a base font-size. If you then use lengths with relative units like em and rem, the computed pixel values are based off of that base font-size.

<meta name="text=scale" value="scale">
<style>
html {
  /* Don't set a base font-size here! */
}
</style>

From the rendering tab in DevTools you can emulate the preferred font-size. Use the dropdown to change the value.

Learn more about <meta name=text-scale>


Part 2: Implement natural interactions

Intuitive, physical motion and natural gestures are key to making web experiences feel as tactile as native applications. And modern CSS makes this easier for you to achieve.

8. linear() easing function

The linear() easing function lets you create complex, custom transition curves (like bounces, springs, or elastic overshoots) by interpolating linearly between an unlimited number of specified progress points.

Browser Support

  • Chrome: 113.
  • Edge: 113.
  • Firefox: 112.
  • Safari: 17.2.

Source

In the following demo, linear() is used to give the dialog a natural easing as it gets shown or hidden.

Learn more about linear()

9. @starting-style

The @starting-style CSS at-rule defines the starting values for properties on an element that you want to transition from when the element is first rendered in the DOM or when its display changes from none to a visible value, to enable smooth entry transitions.

Browser Support

  • Chrome: 117.
  • Edge: 117.
  • Firefox: 129.
  • Safari: 17.5.

Source

In the previous demo this is used to animate-in the <dialog> as it first becomes visible.

10. transition-behavior: allow-discrete

The transition-behavior property (often used as allow-discrete in the transition shorthand) lets you transition discrete properties like display or overlay, ensuring elements remain visible during exit animations before being hidden.

Browser Support

  • Chrome: 117.
  • Edge: 117.
  • Firefox: 129.
  • Safari: 17.4.

Source

11. sibling-index() and sibling-count()

The sibling-index() and sibling-count() CSS functions return integers representing an element's 1-based position among its siblings and the total sibling count, respectively. They are perfect for calculating staggered animation delays dynamically in CSS without JavaScript.

Browser Support

  • Chrome: 138.
  • Edge: 138.
  • Firefox: not supported.
  • Safari: 26.2.

Source

Browser Support

  • Chrome: 138.
  • Edge: 138.
  • Firefox: not supported.
  • Safari: 26.2.

Source

In this demo the contents of the dialog are staggered by using the sibling-index() in the animation-delay

dialog[open] > * {
  animation:
    content-entry 0.6s var(--spring) forwards;
  
  /* 0.2s delay for the first item, then staggering by 0.05s via sibling-index()
  */
  animation-delay:
    calc(sibling-index() * 0.05s + 0.2s);
}

12. Dialog light dismiss (closedby attribute)

The closedby attribute on the <dialog> element (with value any) lets you use declarative "light dismiss" behavior, automatically closing modal dialogs when clicking outside them or pressing ESC, without requiring custom JavaScript.

Browser Support

  • Chrome: 134.
  • Edge: 134.
  • Firefox: 141.
  • Safari: not supported.

Source

You can try it in the previous demo.

13. corner-shape

The experimental corner-shape shorthand property lets developers modify rounded corners (from border-radius) to create custom visual shapes like bevel, scoop, notch, or squircle (via superellipse()). Borders, shadows, and focus outlines automatically conform to the shape.

Browser Support

  • Chrome: 139.
  • Edge: 139.
  • Firefox: not supported.
  • Safari: not supported.

Source


Part 3: Provide guided navigation

Guiding the user journey helps maintain context and understand the application's flow, eliminating disorienting reloads. You can do this in a few ways, including with view transitions, which have received a few recent updates.

14. Same-document view transitions

Part of the View Transition API, same-document transitions provide a mechanism for animating between DOM states in single-page applications (SPAs) by capturing snapshots and transitioning them using CSS.

Browser Support

  • Chrome: 111.
  • Edge: 111.
  • Firefox: 144.
  • Safari: 18.

Source

Learn more about same-document view transitions

15. Cross-document view transitions

Extends the View Transition API to multi-page applications (MPAs), letting you create seamless, animated transitions when navigating between different documents by matching elements with the same view-transition-name across pages.

Browser Support

  • Chrome: 126.
  • Edge: 126.
  • Firefox: not supported.
  • Safari: 18.2.

Source

Learn more about cross-document view transitions

16. Element-scoped view transitions

Introduced in Chrome 147, element-scoped view transitions let you run a view transition only on a specific DOM subtree (using element.startViewTransition()) while keeping the rest of the page active and interactive.

Browser Support

  • Chrome: 147.
  • Edge: 147.
  • Firefox: not supported.
  • Safari: not supported.

When starting an element-scoped view transition, it runs in isolation: it only scans that subtree for elements with a view-transition-name and the ::view-transition pseudo gets injected onto the scope root itself. The isolation is possible thanks to the automatic application of view-transition-scope: all.

This allows multiple view transitions to run at the same time, as well as the nesting of view transitions: while the items in these lists are getting shuffled, you can also swap the lists themselves.

Additionally the group pseudos are automatically nested and the overflow of the enclosing group-children pseudo is clipped when needed.

Scoped view transitions are perfect for micro-interactions and in-page stateful morphing, giving the user more context when there is a visual change. This is a great way to enhance the usability of your application while also elevating how it looks and feels. These little things make a big difference!

Learn more about element-scoped view transitions

17. Two-phase view transitions

This is an experimental feature that immediately starts a cross-document view transition without waiting for the new DOM to be ready, first transitioning into an intermediary skeleton screen or loading UI, before continuing with the cross-document view transition.

Learn more about two-phase view transitions

18. Scroll-driven animations

Scroll-driven animations link the progress of a CSS animation directly to the scroll position of a scroll container, letting developers build scroll-based interfaces like efficient parallax effects and scroll indicators.

Browser Support

  • Chrome: 115.
  • Edge: 115.
  • Firefox: behind a flag.
  • Safari: 26.

Source

19. Scroll-triggered animations

New to Chrome are scroll-triggered animations. Scroll-triggered animations trigger a standard time-based CSS animation when a scroll boundary is crossed (using timeline-trigger to define the trigger and animation-trigger to play it), providing a declarative alternative to IntersectionObserver.

Browser Support

  • Chrome: 146.
  • Edge: 146.
  • Firefox: not supported.
  • Safari: not supported.

The underlying mechanism for scroll-triggered animations are timeline-triggers which are either active or inactive.

.element {
  timeline-trigger:
    --t
    view()
    contain 25% contain 75% / entry 105% exit -5%
  ;
}

Flip on the visualizer in the following demo to see what is happening: the first range is the activation range and determines when the trigger becomes active. The second range is the active range which determines how long it should remain active.

Learn more about scroll-triggered animations

20. scroll-target-group: auto

You can now build a native CSS scroll-spy which automatically highlights navigation links based on the user's scroll position. By setting scroll-target-group: auto on a navigation list, the browser automatically sets aria-current="true" and applies the :target-current pseudo-class to the active link. :target-current can then be used to further style the active links.

Browser Support

  • Chrome: 140.
  • Edge: 140.
  • Firefox: not supported.
  • Safari: not supported.

Source

Browser Support

  • Chrome: 135.
  • Edge: 135.
  • Firefox: not supported.
  • Safari: not supported.

Source

Learn more about the CSS scroll-spy with scroll-target-group

21. scrollIntoView() container option

The scrollIntoView() method gains a container option. Setting target.scrollIntoView({container: 'nearest'}) limits the scrolling to the nearest ancestor scroller instead of having it bubble all the way up, preventing disorienting page-level scrolling.

Browser Support

  • Chrome: 1.
  • Edge: 79.
  • Firefox: 1.
  • Safari: 3.

Source

Use the checkbox in this demo to toggle the option off and on:

Learn more about container: "nearest"

22. Awaitable programmatic scrolling

All programmatic scroll methods (like scroll(), scrollTo(), and scrollIntoView()) now return a Promise. This lets developers await the completion of smooth scroll animations before executing subsequent logic (like adding a highlight effect).

Browser Support

  • Chrome: 1.
  • Edge: 79.
  • Firefox: 1.
  • Safari: 3.

Source

In the following demo here you can see it in action: the element is first scrolled into view, after which a highlight effect is added to it.


Part 4: Maximize content, reduce noise

One of the most frustrating web experiences is expecting to see content and getting blocked by intrusive pop ups or banners. Prioritize content area by eliminating visual clutter and application borders, moving secondary actions behind layered UI.

23. Scroll-state queries (scrolled)

Part of CSS Container Queries, scroll-state queries let you style descendants based on the scroll state of a container (with container-type: scroll-state). The scrolled query (for example, scroll-state(scrolled: bottom)) detects the direction of the most recent relative scroll, enabling patterns like the "Hidey Bar."

Browser Support

  • Chrome: 133.
  • Edge: 133.
  • Firefox: not supported.
  • Safari: not supported.

Learn more about the "Hidey Bar" pattern

24. Anchored container queries

CSS Anchor Positioning includes anchored container queries, which let you check which fallback position (for example, fallback: bottom or fallback: flip-block) is currently active on an anchor-positioned element, enabling dynamic updates to styling an anchor positioned element (like tooltip arrows).

Browser Support

  • Chrome: 143.
  • Edge: 143.
  • Firefox: not supported.
  • Safari: not supported.

In the following demo, an anchor positioned popover repositions itself based on its fallback position and position in the viewport using anchored container queries. When the tooltip opens above the invoker it animates bottom-up, from the source. When it is below the invoker it animates top-down.

25. CSS border-shape

The border-shape property lets you define non-rectangular borders using the same shape syntax as clip-path. Unlike clipping, border-shape keeps borders, outlines, and shadows visually aligned with the custom shape. It also goes beyond the capabilities of corner-shape, as border-shape is much more flexible.

Browser Support

  • Chrome: 147.
  • Edge: 147.
  • Firefox: not supported.
  • Safari: not supported.

26. CSS shape() function

The CSS shape() function lets you define complex geometric paths inline in CSS. It can be used with properties like clip-path, border-shape, or shape-outside to create organic, non-rectangular shapes that content can float against.

Browser Support

  • Chrome: 135.
  • Edge: 135.
  • Firefox: 148.
  • Safari: 18.4.

Source

27. Sticky positioning per axis

Thanks to a recent change in the overflow specification that allows containers to be a scroller for only a single axis, sticky positioning can now track two different scroll containers (one for each axis) simultaneously. This makes a sticky first column and top row in a table work as expected even inside single-axis scroll containers.

Browser Support

  • Chrome: 56.
  • Edge: 16.
  • Firefox: 32.
  • Safari: 13.

This feature is available for testing in Chrome 148 with the Experimental Web Platform Features flag enabled.

Learn more about position: sticky per axis


Part 5: Adapt to the form factor

One of the most valuable things about the web is its flexibility. Users can navigate the web from a variety of devices, each with their own interaction mechanisms. Layouts should fundamentally adapt to the device and input method, whether a virtual keyboard is open, or touch targets are active. Keeping the form factor in mind when designing for the web gives your site or web app that extra finesse and aligns user expectations.

28. Overscroll gestures (swipeable areas)

One example of adapting to form factor is the ability to use swipe and gesture based interactions on the mobile web. You can use scrollers to achieve some of these effects, but it's not always an intuitive approach.

The Chrome team is working on a proposed declarative solution, in discussion with OpenUI community group, that lets you create native, gesture-driven swipeable areas (for example, swipeable Gmail lists or swipe-dismiss side menus) using overscrollcontainer and command invokers, working across touch and scroll naturally.

Learn more about overscroll gestures


29. HTML-in-Canvas

The HTML-in-Canvas API is a major paradigm shift, letting developers place real DOM elements inside a <canvas> (using the layoutsubtree attribute). These elements remain fully searchable, accessible, and support browser features like autofill, while letting WebGL/WebGPU shaders interact with them natively.


Lightning round

A quick-fire look at some other powerful features pushing the web forward.

30. DOM state-preserving move (moveBefore())

The moveBefore() DOM method lets you reparent DOM nodes (for example, playing videos, iframes, or focused inputs) without destroying their state or triggering reloads.

This means videos keep playing, iframes don't reload, CSS animations don’t restart, and input fields keep their focus as you reparent them across your layout.

Browser Support

  • Chrome: 133.
  • Edge: 133.
  • Firefox: 144.
  • Safari: not supported.

Source

Learn more about moveBefore()

31. CSS text-fit

text-fit is an experimental CSS property that dynamically scales font-size to precisely fit lines of text to the exact width of their containing element (for example, text-fit: grow per-line-all).

Learn more about text-fit

32. CSS text-box (text-box-trim and text-box-edge)

The text-box property (and its longhands text-box-trim and text-box-edge) trims the vertical space (leading) above and below text, ensuring perfect vertical alignment and centering.

Browser Support

  • Chrome: 133.
  • Edge: 133.
  • Firefox: behind a flag.
  • Safari: 18.2.

Source

Learn more about text-trim

33. CSS gap decorations

CSS gap decorations bring column-rule to grid and flexbox, and introduce a new row-rule property, letting developers style the gutters between rows and columns. No more messing with borders or pseudo-elements to style the rules between the rows and columns.

Browser Support

  • Chrome: 149.
  • Edge: 149.
  • Firefox: not supported.
  • Safari: not supported.

Learn more about CSS Gap Decorations

34. Scrollbar-aware viewport units (vw, vh, etc.)

Viewport units like vw and vh automatically subtract the size of scrollbars (if guaranteed to be visible, using overflow-y: scroll or scrollbar-gutter: stable declared on :root), preventing accidental horizontal overflow when setting elements to 100vw.

Browser Support

  • Chrome: 20.
  • Edge: 12.
  • Firefox: 19.
  • Safari: 6.

Learn more about scrollbar-aware viewport units

35. JavaScript access to pseudo-elements

Web APIs now expose CSS pseudo-elements (like ::before or ::after) to JavaScript.

You can retrieve a CSSPseudoElement instance using Element.pseudo(type) and check which pseudo-element triggered an event using Event.pseudoTarget.

Browser Support

  • Chrome: 149.
  • Edge: 149.
  • Firefox: not supported.
  • Safari: not supported.

Learn more about CSSPseudoElement

Conclusion

That's it for our roundup of What's New in Web UI. We hope you take these features and build some great interfaces with them. Until next year!