![Bramus](https://web.dev/images/authors/bramus.jpg) Bramus [X](https://twitter.com/bramus) [GitHub](https://github.com/bramus) [Mastodon](https://front-end.social/@bramus) [Bluesky](https://bsky.app/profile/bram.us) [Homepage](https://www.bram.us/) ![Una Kravets](https://web.dev/images/authors/unakravets.jpg) Una Kravets [X](https://twitter.com/una) [Mastodon](https://front-end.social/@una) [Homepage](https://una.im)

<br />


Published: July 1, 2026

<br />

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.
[Video](https://www.youtube.com/watch?v=uT7MVcCQ4rw)

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()`](https://developer.mozilla.org/docs/Web/CSS/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_1b8f79153b2bc89278a67fc2535263a1edf5b104bf8c0fd0e808db30a4951cc8.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="400" style="width: 100%;" scrolling="no" title="Contrast Color Demo" src="https://codepen.io/web-dot-dev/embed/jEVrWEY?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/jEVrWEY">
Contrast Color Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about `contrast-color()`](https://goo.gle/contrast-color)

### 2. `light-dark()`

The [`light-dark()`](https://developer.mozilla.org/docs/Web/CSS/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).

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_af7a8d4fff2f9da511b7cc9c27bdd838fc825d6bca9d34fe9ad825568c312b92.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="750" style="width: 100%;" scrolling="no" title="Modern UI Theming Demo" src="https://codepen.io/web-dot-dev/embed/azBZveX?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/azBZveX">
Modern UI Theming Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_bd22a159f6d0bc722153edc70e19cad9a5ab7d4e46aed5cc62d044c31788dc4c.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

- [Learn more about `light-dark()`](https://goo.gle/light-dark)
- [Learn more about `light-dark()` with images](https://goo.gle/light-dark-images)

### 3. CSS custom functions (`@function`)

The [`@function`](https://developer.mozilla.org/docs/Web/CSS/@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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_83dc4266c182b0477a2fdf3166ad6eba3c53946a7ce2b731fd9713a011c72033.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

Combined with [container style queries](https://developer.chrome.com/blog/new-in-web-ui-io26.md.txt#4_container_style_queries) and the [CSS `if()` function](https://developer.chrome.com/blog/new-in-web-ui-io26.md.txt#5_css_if_function), you can create a custom `--light-dark()` function that works with *any* type of value, as shown in this demo:
<iframe height="500" style="width: 100%;" scrolling="no" title="Dynamic Modern UI Theming Demo" src="https://codepen.io/web-dot-dev/embed/JobKGoq?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/JobKGoq">
Dynamic Modern UI Theming Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

- [Learn more about `@function`](https://goo.gle/at-function)
- [Learn more about `--light-dark()`](https://goo.gle/custom-light-dark)

### 4. Container style queries

Part of CSS Container Queries, [style queries](https://developer.chrome.com/docs/css-ui/style-queries.md.txt) 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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_97ce08746fd7dd039a6b9db9c33b552e5b09621f3d788ed55cb35ad71df9f57c.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

In this demo, style queries are used to set the colors based on a `--theme` custom property.
<iframe height="750" style="width: 100%;" scrolling="no" title="Modern UI Theming Demo" src="https://codepen.io/web-dot-dev/embed/azBZveX?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/azBZveX">
Modern UI Theming Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

```css
@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](https://goo.gle/style-queries)

### 5. CSS `if()` function

The [`if()`](https://developer.mozilla.org/docs/Web/CSS/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_5967b4e101cb3dc4e058b1428efd30e8ce38a9a466a4afe0db9d4777b3e4a590.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

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

```css
--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:

```css
@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`](https://goo.gle/at-rule)

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

The [`text-scale`](https://developer.mozilla.org/docs/Web/HTML/Element/meta/name/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_ba9fc4c25bf071c7f376d62877d989f2102cd752f57e4f5b93ea89b97f114339.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

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.

```html
<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>`](https://goo.gle/meta-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()`](https://developer.mozilla.org/docs/Web/CSS/easing-function/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_5eb84e7e1ef3d84c01c90c07abc4d1171f3456985635f085beaada57a7f49f16.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

In the following demo, `linear()` is used to give the dialog a natural easing as it gets shown or hidden.
<iframe height="600" style="width: 100%;" scrolling="no" title="Natural Easings Dialog Demo" src="https://codepen.io/web-dot-dev/embed/pvNbgJL?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/pvNbgJL">
Natural Easings Dialog Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about `linear()`](https://goo.gle/css-linear-function)

### 9. `@starting-style`

The [`@starting-style`](https://developer.mozilla.org/docs/Web/CSS/@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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_5c2f8ac66a3ab96469d525ce8a5b2f3c8a6d684526db8075a32066deee2347dc.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

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`](https://developer.mozilla.org/docs/Web/CSS/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_d1ce846b9770557fdeba887bbd55b445a18b6e694ebb58c9fbecc8cffce83a82.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="700" style="width: 100%;" scrolling="no" title="Natural Easings Dialog Transition Demo" src="https://codepen.io/web-dot-dev/embed/RNoRrWa?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/RNoRrWa">
Natural Easings Dialog Transition Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

> [!NOTE]
> **Note:** To learn more about animations, starting-style, easings, and more, check out [Web animations today and tomorrow](https://goo.gle/web-animations-today-and-tomorrow) by Bramus, as presented at Google I/O 2025

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

The [`sibling-index()`](https://developer.mozilla.org/docs/Web/CSS/sibling-index) and [`sibling-count()`](https://developer.mozilla.org/docs/Web/CSS/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_9030c87b36de5a5da226568c18b8f06023a9f39a1e58b38c9651b182e6a2790a.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

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

```css
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);
}
```
<iframe height="700" style="width: 100%;" scrolling="no" title="Natural Easings Dialog Transition Demo" src="https://codepen.io/web-dot-dev/embed/RNoRrWa?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/RNoRrWa">
Natural Easings Dialog Transition Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

### 12. Dialog light dismiss (`closedby` attribute)

The [`closedby`](https://developer.mozilla.org/docs/Web/API/HTMLDialogElement/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 <kbd>ESC</kbd>, without requiring custom JavaScript.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_4d109dffceb5cd3e8bae4130ec973a04859ad5fec443b4812bd731684dfc332d.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

You can try it in the previous demo.

### 13. `corner-shape`

The experimental [`corner-shape`](https://developer.mozilla.org/docs/Web/CSS/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_a86033a37ce7407de82c2957f9cf359c006c8338db5f9354b18a5264604c72ed.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="700" style="width: 100%;" scrolling="no" title="Corner Shape Demo" src="https://codepen.io/web-dot-dev/embed/KwNMVdo?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/KwNMVdo">
Corner Shape Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

*** ** * ** ***

## 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](https://developer.mozilla.org/docs/Web/API/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_a76095a01630631774cba9ec5345ab4db2a38bbb5a7239f9bae2d957bc09d861.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

[Learn more about same-document view transitions](https://goo.gle/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_50819f82e1ed78f00ba73d8c85b184d2ad3f73f7b182c3ab57454d547522ec01.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

[Learn more about cross-document view transitions](https://goo.gle/cross-document-view-transitions)

### 16. Element-scoped view transitions

Introduced in Chrome 147, [element-scoped view transitions](https://developer.chrome.com/docs/css-ui/view-transitions/element-scoped-view-transitions.md.txt) 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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_54980dc4ffff4410391ccc4d1af476d1282d990e4d83cd18932a308d8e037334.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

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.
<iframe height="600" style="width: 100%;" scrolling="no" title="Element-Scoped View Transitions Lists Demo" src="https://codepen.io/web-dot-dev/embed/ogzpdLE?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/ogzpdLE">
Element-Scoped View Transitions Lists Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

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!
<iframe height="300" style="width: 100%;" scrolling="no" title="Morph Transition Demo 1" src="https://codepen.io/web-dot-dev/embed/myOEVVE?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/myOEVVE">
Morph Transition Demo 1</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe> <iframe height="300" style="width: 100%;" scrolling="no" title="Morph Transition Demo 2" src="https://codepen.io/web-dot-dev/embed/QwGEyya?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/QwGEyya">
Morph Transition Demo 2</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about element-scoped view transitions](https://goo.gle/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](https://goo.gle/two-phase-view-transitions-explainer)

### 18. Scroll-driven animations

[Scroll-driven animations](https://developer.mozilla.org/docs/Web/CSS/Guides/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_50ed63eb4f1a3acc389072af28ddd44b31df92e27b2524f3e6a499be00ba6c48.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="500" style="width: 100%;" scrolling="no" title="Scroll-Driven Animations Demo" src="https://scroll-driven-animations.style/demos/cover-to-fixed-header/css/?embed=true" frameborder="no" loading="lazy" allowtransparency="true"><a href="https://scroll-driven-animations.style/demos/cover-to-fixed-header/css/">Check out the demo</a></iframe>

- [Learn more about scroll-driven animations](https://developer.chrome.com/docs/css-ui/scroll-driven-animations.md.txt)
- [Check out multiple scroll-driven animations demos](https://scroll-driven-animations.style/)
- [Learn scroll-driven animations with this 10-part free video course](https://scroll-driven-animations.style/#learn)

### 19. Scroll-triggered animations

New to Chrome are scroll-**triggered** animations. [Scroll-triggered animations](https://developer.chrome.com/blog/scroll-triggered-animations.md.txt) 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.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='-10 -10 276 276'%3E%3ClinearGradient id='a' x1='145' x2='34' y1='253' y2='61' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%231e8e3e'/%3E%3Cstop offset='1' stop-color='%2334a853'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='111' x2='222' y1='254' y2='62' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23fcc934'/%3E%3Cstop offset='1' stop-color='%23fbbc04'/%3E%3C/linearGradient%3E%3ClinearGradient id='c' x1='17' x2='239' y1='80' y2='80' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23d93025'/%3E%3Cstop offset='1' stop-color='%23ea4335'/%3E%3C/linearGradient%3E%3Ccircle cx='128' cy='128' r='64' fill='%23fff'/%3E%3Cpath fill='url(%23a)' d='M96 183a64 64 0 0 1-23-23L17 64a128 128 0 0 0 111 192l55-96a64 64 0 0 1-87 23Z'/%3E%3Cpath fill='url(%23b)' d='M192 128a64 64 0 0 1-9 32l-55 96A128 128 0 0 0 239 64H128a64 64 0 0 1 64 64Z'/%3E%3Ccircle cx='128' cy='128' r='52' fill='%231a73e8'/%3E%3Cpath fill='url(%23c)' d='M96 73a64 64 0 0 1 32-9h111a128 128 0 0 0-222 0l56 96a64 64 0 0 1 23-87Z'/%3E%3C/svg%3E)
- ![Edge: 146.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 27600 27600'%3E%3ClinearGradient id='A' gradientUnits='userSpaceOnUse'/%3E%3ClinearGradient id='B' x1='6870' x2='24704' y1='18705' y2='18705' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%230c59a4'/%3E%3Cstop offset='1' stop-color='%23114a8b'/%3E%3C/linearGradient%3E%3ClinearGradient id='C' x1='16272' x2='5133' y1='10968' y2='23102' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%231b9de2'/%3E%3Cstop offset='.16' stop-color='%231595df'/%3E%3Cstop offset='.67' stop-color='%230680d7'/%3E%3Cstop offset='1' stop-color='%230078d4'/%3E%3C/linearGradient%3E%3CradialGradient id='D' cx='16720' cy='18747' r='9538' xlink:href='%23A'%3E%3Cstop offset='.72' stop-opacity='0'/%3E%3Cstop offset='.95' stop-opacity='.53'/%3E%3Cstop offset='1'/%3E%3C/radialGradient%3E%3CradialGradient id='E' cx='7130' cy='19866' r='14324' gradientTransform='matrix(.14843 -.98892 .79688 .1196 -8759 25542)' xlink:href='%23A'%3E%3Cstop offset='.76' stop-opacity='0'/%3E%3Cstop offset='.95' stop-opacity='.5'/%3E%3Cstop offset='1'/%3E%3C/radialGradient%3E%3CradialGradient id='F' cx='2523' cy='4680' r='20243' gradientTransform='matrix(-.03715 .99931 -2.12836 -.07913 13579 3530)' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%2335c1f1'/%3E%3Cstop offset='.11' stop-color='%2334c1ed'/%3E%3Cstop offset='.23' stop-color='%232fc2df'/%3E%3Cstop offset='.31' stop-color='%232bc3d2'/%3E%3Cstop offset='.67' stop-color='%2336c752'/%3E%3C/radialGradient%3E%3CradialGradient id='G' cx='24247' cy='7758' r='9734' gradientTransform='matrix(.28109 .95968 -.78353 .22949 24510 -16292)' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%2366eb6e'/%3E%3Cstop offset='1' stop-color='%2366eb6e' stop-opacity='0'/%3E%3C/radialGradient%3E%3Cpath id='H' d='M24105 20053a9345 9345 0 01-1053 472 10202 10202 0 01-3590 646c-4732 0-8855-3255-8855-7432 0-1175 680-2193 1643-2729-4280 180-5380 4640-5380 7253 0 7387 6810 8137 8276 8137 791 0 1984-230 2704-456l130-44a12834 12834 0 006660-5282c220-350-168-757-535-565z'/%3E%3Cpath id='I' d='M11571 25141a7913 7913 0 01-2273-2137 8145 8145 0 01-1514-4740 8093 8093 0 013093-6395 8082 8082 0 011373-859c312-148 846-414 1554-404a3236 3236 0 012569 1297 3184 3184 0 01636 1866c0-21 2446-7960-8005-7960-4390 0-8004 4166-8004 7820 0 2319 538 4170 1212 5604a12833 12833 0 007684 6757 12795 12795 0 003908 610c1414 0 2774-233 4045-656a7575 7575 0 01-6278-803z'/%3E%3Cpath id='J' d='M16231 15886c-80 105-330 250-330 566 0 260 170 512 472 723 1438 1003 4149 868 4156 868a5954 5954 0 003027-839 6147 6147 0 001133-850 6180 6180 0 001910-4437c26-2242-796-3732-1133-4392-2120-4141-6694-6525-11668-6525-7011 0-12703 5635-12798 12620 47-3654 3679-6605 7996-6605 350 0 2346 34 4200 1007 1634 858 2490 1894 3086 2921 618 1067 728 2415 728 2952s-271 1333-780 1990z'/%3E%3Cuse fill='url(%23B)' xlink:href='%23H'/%3E%3Cuse fill='url(%23D)' opacity='.35' xlink:href='%23H'/%3E%3Cuse fill='url(%23C)' xlink:href='%23I'/%3E%3Cuse fill='url(%23E)' opacity='.4' xlink:href='%23I'/%3E%3Cuse fill='url(%23F)' xlink:href='%23J'/%3E%3Cuse fill='url(%23G)' xlink:href='%23J'/%3E%3C/svg%3E)
- ![Firefox: not supported.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 512 512'%3E%3Cdefs%3E%3CradialGradient id='ff-b' cx='428.5' cy='55.1' r='501' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23ffbd4f'/%3E%3Cstop offset='.2' stop-color='%23ffac31'/%3E%3Cstop offset='.3' stop-color='%23ff9d17'/%3E%3Cstop offset='.3' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff563b'/%3E%3Cstop offset='.5' stop-color='%23ff3750'/%3E%3Cstop offset='.7' stop-color='%23f5156c'/%3E%3Cstop offset='.8' stop-color='%23eb0878'/%3E%3Cstop offset='.9' stop-color='%23e50080'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-c' cx='245.4' cy='259.9' r='501' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.3' stop-color='%23960e18'/%3E%3Cstop offset='.3' stop-color='%23b11927' stop-opacity='.7'/%3E%3Cstop offset='.4' stop-color='%23db293d' stop-opacity='.3'/%3E%3Cstop offset='.5' stop-color='%23f5334b' stop-opacity='.1'/%3E%3Cstop offset='.5' stop-color='%23ff3750' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-d' cx='305.8' cy='-58.6' r='363' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.3' stop-color='%23ffdc3e'/%3E%3Cstop offset='.5' stop-color='%23ff9d12'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-e' cx='190' cy='390.8' r='238.6' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.3' stop-color='%233a8ee6'/%3E%3Cstop offset='.5' stop-color='%235c79f0'/%3E%3Cstop offset='.7' stop-color='%239059ff'/%3E%3Cstop offset='1' stop-color='%23c139e6'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-f' cx='252.2' cy='201.3' r='126.5' gradientTransform='matrix(1 0 0 1 -48 31)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.2' stop-color='%239059ff' stop-opacity='0'/%3E%3Cstop offset='.3' stop-color='%238c4ff3' stop-opacity='.1'/%3E%3Cstop offset='.8' stop-color='%237716a8' stop-opacity='.5'/%3E%3Cstop offset='1' stop-color='%236e008b' stop-opacity='.6'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-g' cx='239.1' cy='34.6' r='171.6' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23ffe226'/%3E%3Cstop offset='.1' stop-color='%23ffdb27'/%3E%3Cstop offset='.3' stop-color='%23ffc82a'/%3E%3Cstop offset='.5' stop-color='%23ffa930'/%3E%3Cstop offset='.7' stop-color='%23ff7e37'/%3E%3Cstop offset='.8' stop-color='%23ff7139'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-h' cx='374' cy='-74.3' r='732.2' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3Cstop offset='.6' stop-color='%23ff5634'/%3E%3Cstop offset='.7' stop-color='%23ff3647'/%3E%3Cstop offset='.9' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-i' cx='304.6' cy='7.1' r='536.4' gradientTransform='rotate(84 303 4)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23fff44f'/%3E%3Cstop offset='.1' stop-color='%23ffe847'/%3E%3Cstop offset='.2' stop-color='%23ffc830'/%3E%3Cstop offset='.3' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff8b16'/%3E%3Cstop offset='.5' stop-color='%23ff672a'/%3E%3Cstop offset='.6' stop-color='%23ff3647'/%3E%3Cstop offset='.7' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-j' cx='235' cy='98.1' r='457.1' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3Cstop offset='.6' stop-color='%23ff5634'/%3E%3Cstop offset='.7' stop-color='%23ff3647'/%3E%3Cstop offset='.9' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-k' cx='355.7' cy='124.9' r='500.3' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.2' stop-color='%23ffe141'/%3E%3Cstop offset='.5' stop-color='%23ffaf1e'/%3E%3Cstop offset='.6' stop-color='%23ff980e'/%3E%3C/radialGradient%3E%3ClinearGradient id='ff-a' x1='446.9' y1='76.8' x2='47.9' y2='461.8' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.1' stop-color='%23ffe847'/%3E%3Cstop offset='.2' stop-color='%23ffc830'/%3E%3Cstop offset='.4' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff8b16'/%3E%3Cstop offset='.5' stop-color='%23ff672a'/%3E%3Cstop offset='.5' stop-color='%23ff3647'/%3E%3Cstop offset='.7' stop-color='%23e31587'/%3E%3C/linearGradient%3E%3ClinearGradient id='ff-l' x1='442.1' y1='74.8' x2='102.6' y2='414.3' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.2' stop-color='%23fff44f' stop-opacity='.8'/%3E%3Cstop offset='.3' stop-color='%23fff44f' stop-opacity='.6'/%3E%3Cstop offset='.5' stop-color='%23fff44f' stop-opacity='.2'/%3E%3Cstop offset='.6' stop-color='%23fff44f' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M479 166c-11-25-32-52-49-60a249 249 0 0 1 25 73c-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-60 35-81 101-83 134a120 120 0 0 0-66 25 71 71 0 0 0-6-5 111 111 0 0 1-1-58c-25 11-44 29-58 44-9-12-9-52-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73l-1 2-2 15a229 229 0 0 0-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121zM202 355l3 1-3-1zm55-145zm198-31z' fill='url(%23ff-a)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60 14 26 22 53 25 72v1a207 207 0 0 1-206 279c-113-3-212-87-231-197-3-17 0-26 2-40-2 11-3 14-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121z' fill='url(%23ff-b)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60 14 26 22 53 25 72v1a207 207 0 0 1-206 279c-113-3-212-87-231-197-3-17 0-26 2-40-2 11-3 14-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121z' fill='url(%23ff-c)'/%3E%3Cpath d='m362 195 1 1a130 130 0 0 0-22-29C266 92 322 5 331 0c-60 35-81 101-83 134l9-1c45 0 84 25 105 62z' fill='url(%23ff-d)'/%3E%3Cpath d='M257 210c-1 6-22 26-29 26-68 0-80 41-80 41 3 35 28 64 57 79l4 2 7 3a107 107 0 0 0 31 6c120 6 143-143 57-186 22-4 45 5 58 14-21-37-60-62-105-62l-9 1a120 120 0 0 0-66 25l17 16c16 16 58 33 58 35z' fill='url(%23ff-e)'/%3E%3Cpath d='M257 210c-1 6-22 26-29 26-68 0-80 41-80 41 3 35 28 64 57 79l4 2 7 3a107 107 0 0 0 31 6c120 6 143-143 57-186 22-4 45 5 58 14-21-37-60-62-105-62l-9 1a120 120 0 0 0-66 25l17 16c16 16 58 33 58 35z' fill='url(%23ff-f)'/%3E%3Cpath d='m171 151 5 3a111 111 0 0 1-1-58c-25 11-44 29-58 44 1 0 36 0 54 11z' fill='url(%23ff-g)'/%3E%3Cpath d='M18 261a242 242 0 0 0 231 197 207 207 0 0 0 206-279c8 56-20 110-64 146-86 71-169 43-186 31l-3-1c-50-24-71-70-67-110-42 0-57-35-57-35s38-28 89-4c46 22 90 4 90 4 0-2-42-19-58-35l-17-16a71 71 0 0 0-6-5l-5-3c-18-11-52-11-54-11-9-12-9-51-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73c0 1-9 38-5 57z' fill='url(%23ff-h)'/%3E%3Cpath d='M341 167a130 130 0 0 1 22 29 46 46 0 0 1 4 3c55 50 26 121 24 126 44-36 72-90 64-146-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-9 5-65 92 10 167z' fill='url(%23ff-i)'/%3E%3Cpath d='M367 199a46 46 0 0 0-4-3l-1-1c-13-9-36-18-58-15 86 44 63 193-57 187a107 107 0 0 1-31-6 131 131 0 0 1-11-5c17 12 99 39 186-31 2-5 31-76-24-126z' fill='url(%23ff-j)'/%3E%3Cpath d='M148 277s12-41 80-41c7 0 28-20 29-26s-44 18-90-4c-51-24-89 4-89 4s15 35 57 35c-4 40 16 85 67 110l3 1c-29-15-54-44-57-79z' fill='url(%23ff-k)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60a249 249 0 0 1 25 73c-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-60 35-81 101-83 134l9-1c45 0 84 25 105 62-13-9-36-18-58-14 86 43 63 192-57 186a107 107 0 0 1-31-6 131 131 0 0 1-11-5l-3-1 3 1c-29-15-54-44-57-79 0 0 12-41 80-41 7 0 28-20 29-26 0-2-42-19-58-35l-17-16a71 71 0 0 0-6-5 111 111 0 0 1-1-58c-25 11-44 29-58 44-9-12-9-52-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73l-1 2-2 15a279 279 0 0 0-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121zm-24 13z' fill='url(%23ff-l)'/%3E%3C/svg%3E)
- ![Safari: not supported.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='195 190 135 135'%3E%3Cdefs%3E%3ClinearGradient id='s-a' x1='132.6' x2='134.4' y1='111.7' y2='-105.3' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23d2d2d2' /%3E%3Cstop offset='.5' stop-color='%23f2f2f2' /%3E%3Cstop offset='1' stop-color='%23fff' /%3E%3C/linearGradient%3E%3ClinearGradient id='s-b' gradientUnits='userSpaceOnUse' /%3E%3ClinearGradient id='s-c' x1='65.4' x2='67.4' y1='115.7' y2='17.1' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23005ad5' /%3E%3Cstop offset='.2' stop-color='%230875f0' /%3E%3Cstop offset='.3' stop-color='%23218cee' /%3E%3Cstop offset='.6' stop-color='%2327a5f3' /%3E%3Cstop offset='.8' stop-color='%2325aaf2' /%3E%3Cstop offset='1' stop-color='%2321aaef' /%3E%3C/linearGradient%3E%3ClinearGradient id='s-d' x1='158.7' x2='176.3' y1='96.7' y2='79.5' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23c72e24' /%3E%3Cstop offset='1' stop-color='%23fd3b2f' /%3E%3C/linearGradient%3E%3CradialGradient id='s-i' cx='-69.9' cy='69.3' r='54' gradientTransform='matrix(.9 -.01 .04 2.72 -9 -120)' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%2324a5f3' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%231e8ceb' /%3E%3C/radialGradient%3E%3CradialGradient id='s-j' cx='109.3' cy='13.8' r='93.1' gradientTransform='matrix(-.02 1.1 -1.04 -.02 137 -115)' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%235488d6' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%235d96eb' /%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='220' height='220' x='22' y='-107' fill='url(%23s-a)' ry='49' transform='matrix(.57 0 0 .57 187 256)' /%3E%3Cg transform='translate(194 190)'%3E%3Ccircle cx='67.8' cy='67.7' fill='url(%23s-c)' paint-order='stroke fill markers' r='54' /%3E%3Ccircle cx='-69.9' cy='69.3' fill='url(%23s-i)' transform='translate(138 -2)' r='54' /%3E%3C/g%3E%3Cellipse cx='120' cy='14.2' fill='url(%23s-j)' rx='93.1' ry='93.7' transform='matrix(.58 0 0 .58 192 250)' /%3E%3Cg transform='matrix(.58 0 0 .57 197 182)'%3E%3Cpath fill='%23cac7c8' d='M46 192h1l72-48-7-9-66 57Z' /%3E%3Cpath fill='%23fbfffc' d='M46 191v1l66-57-7-9-59 65Z' /%3E%3Cpath fill='url(%23s-d)' d='m119 144-7-9 66-57-59 66Z' /%3E%3Cpath fill='%23fb645c' d='m105 126 7 9 66-57-1-1-72 49Z' /%3E%3C/g%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-miterlimit='1' stroke-width='1.3' d='m287 278 3-2m-12-17 8-2m-8-3h4m-4-13 8 2m-8 3h4m-1-13 7 3m-4-11 7 4m-2-11 6 6m0-12 6 7m1-11 4 6m4-10 3 7m5-9 2 7m15-7-1 7m10-5-3 7m11-4-4 7m11-2-5 6m16 7-7 4m10 4-7 3m10 6-8 1m8 16-8-2m5 10-7-3m4 11-7-4m2 11-6-5m0 11-5-6m-2 11-4-7m-4 11-3-8m-6 10-1-8m-16 8 2-8m-10 5 3-7m-11 4 4-7m-11 2 5-6m-8 3 3-3m4 8 2-3m5 8 2-4m6 7 1-4m8 5v-4m8 4v-4m9 3-1-4m9 1-2-4m9 0-2-4m9-2-3-3m8-4-3-2m8-5-4-2m7-6-4-1m5-8h-4m4-8h-4m3-9-4 1m1-9-4 2m-1-9-3 2m-2-9-3 3m-4-8-2 3m-5-8-2 4m-6-6-1 3m-8-5v4m-8-4v4m-9-2 1 3m-9 0 2 3m-9 1 2 3m-9 2 3 3m-8 4 3 2m-8 5 4 2m-7 6 4 1m-4 25 4-1m-2 5 7-3m-6 7 4-2m-2 6 7-4m-13-21h8m41-41v-8m0 99v-8m49-42h-8' transform='translate(-65 8)' /%3E%3C/svg%3E)

[Source](https://developer.mozilla.org/docs/Web/CSS/Reference/Properties/animation-trigger)

<br />

<iframe height="500" style="width: 100%;" scrolling="no" title="Scroll-Triggered Animations Demo" src="https://codepen.io/web-dot-dev/embed/qEqNbbe?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/qEqNbbe">
Scroll-Triggered Animations Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

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

```css
.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.
<iframe height="600" style="width: 100%;" scrolling="no" title="Scroll-Triggered Animations Ranges Demo" src="https://codepen.io/web-dot-dev/embed/gbLMPrL?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/gbLMPrL">
Scroll-Triggered Animations Ranges Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about scroll-triggered animations](https://goo.gle/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`](https://developer.mozilla.org/docs/Web/CSS/scroll-target-group) 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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_8d9fcadb4d75e2e527c03c4f6bd2486386437edc310ab1242d4d8c7e62bd4da8.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="500" style="width: 100%;" scrolling="no" title="Basic scroll-target-group" src="https://codepen.io/web-dot-dev/embed/jEymmZd?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/jEymmZd">
Basic scroll-target-group</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about the CSS scroll-spy with `scroll-target-group`](https://goo.gle/css-scrollspy)

### 21. `scrollIntoView()` container option

The [`scrollIntoView()`](https://developer.mozilla.org/docs/Web/API/Element/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_2ea151a33223dd4e9fdf7c1eac9ecefcce243a93584a087e64fafa1a437e91da.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

Use the checkbox in this demo to toggle the option off and on:
<iframe height="600" style="width: 100%;" scrolling="no" title="ScrollIntoView Container Option Demo" src="https://codepen.io/web-dot-dev/embed/emZrZoQ?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/emZrZoQ">
ScrollIntoView Container Option Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about `container: "nearest"`](https://goo.gle/scrollintoview-container)

### 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).

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_9f7e1a7a351a64f21bf710d76f4a39ab4e6d94d76a5bfccd0e1f5df24f289a46.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

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.
<iframe height="500" style="width: 100%;" scrolling="no" title="ScrollIntoView Await Promise Demo" src="https://codepen.io/web-dot-dev/embed/xbROZVo?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/xbROZVo">
ScrollIntoView Await Promise Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

*** ** * ** ***

## 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](https://developer.chrome.com/blog/css-scroll-state-queries.md.txt) (for example, `scroll-state(scrolled: bottom)`) detects the direction of the most recent relative scroll, enabling patterns like the "Hidey Bar."

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_2e1a0c9d9df4c1726de9712f66cf25d89b3e5939024ada87c904f0ca7493e224.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="500" style="width: 100%;" scrolling="no" title="Hidey Bar Demo (Scroll-State Queries)" src="https://codepen.io/web-dot-dev/embed/MYbeKeq?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/MYbeKeq">
Hidey Bar Demo (Scroll-State Queries)</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about the "Hidey Bar" pattern](https://goo.gle/hidey-bar)

### 24. Anchored container queries

CSS Anchor Positioning includes [anchored container queries](https://developer.mozilla.org/docs/Web/CSS/Guides/Anchor_positioning/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).

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_4337597a011518829aaf89c4325dc77bbba67e75d7591655339423d05ca4e1b5.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

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.
<iframe height="500" style="width: 100%;" scrolling="no" title="Anchored Tooltip Demo" src="https://codepen.io/web-dot-dev/embed/LEbZGRY?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/LEbZGRY">
Anchored Tooltip Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

### 25. CSS `border-shape`

The [`border-shape`](https://developer.chrome.com/blog/css-shape.md.txt) 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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_494b4dd26b73cd75790ad4086c8d3bddd82e7d8377914950f9917aec64a3d6ff.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="300" style="width: 100%;" scrolling="no" title="Border Shape Chevron Navigation Demo" src="https://codepen.io/web-dot-dev/embed/KwNMVgR?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/KwNMVgR">
Border Shape Chevron Navigation Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

### 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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_636c851380b7185c4f25b5a7122c60b1dc3107345cd08598ae4810f7a0eee151.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="700" style="width: 100%;" scrolling="no" title="Shape-Outside Wave Generator" src="https://codepen.io/web-dot-dev/embed/OPbXMbm?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/OPbXMbm">
Shape-Outside Wave Generator</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

### 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](https://developer.mozilla.org/docs/Web/CSS/position) 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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_a6fad8815f48dfecf618c5fccbd6c817ffe05873c76d164e95434f180b4176fb.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="700" style="width: 100%;" scrolling="no" title="Sticky Positioning per Axis Demo" src="https://codepen.io/web-dot-dev/embed/VYmjePe?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/VYmjePe">
Sticky Positioning per Axis Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

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

[Learn more about `position: sticky` per axis](https://goo.gle/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](https://goo.gle/overscroll-gestures-open-ui)

*** ** * ** ***

### 29. HTML-in-Canvas

The [HTML-in-Canvas API](https://developer.chrome.com/blog/html-in-canvas-origin-trial.md.txt) 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.

- [Learn more about HTML-in-Canvas](https://developer.chrome.com/blog/html-in-canvas-origin-trial.md.txt)
- [Explore HTML-in-Canvas demos](https://goo.gle/html-in-canvas-demos)

*** ** * ** ***

## Lightning round

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

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

The [`moveBefore()`](https://developer.mozilla.org/docs/Web/API/Element/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_1447dd8b300d0a7d92e3a9d10b1cf54a2e88718f76e1f3df58e56385a4e4cc57.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="700" style="width: 100%;" scrolling="no" title="moveBefore() State-Preserving DOM Move Demo" src="https://codepen.io/web-dot-dev/embed/QwNrNPQ?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/QwNrNPQ">
moveBefore() State-Preserving DOM Move Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about `moveBefore()`](https://goo.gle/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`).
<iframe height="600" style="width: 100%;" scrolling="no" title="CSS text-fit Demo" src="https://codepen.io/web-dot-dev/embed/jEyGROo?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/jEyGROo">
CSS text-fit Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about `text-fit`](https://goo.gle/css-fit-width-text-explainer)

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

The [`text-box`](https://developer.mozilla.org/docs/Web/CSS/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.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_509920ae7a33d40904663536ce9b226664421c024a6c8148a308ed9b3649a668.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>
<iframe height="700" style="width: 100%;" scrolling="no" title="CSS text-box Playground" src="https://codepen.io/web-dot-dev/embed/RNbyooE?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/RNbyooE">
CSS text-box Playground</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about `text-trim`](https://goo.gle/css-text-box)

### 33. CSS gap decorations

CSS gap decorations bring [`column-rule`](https://developer.mozilla.org/docs/Web/CSS/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.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='-10 -10 276 276'%3E%3ClinearGradient id='a' x1='145' x2='34' y1='253' y2='61' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%231e8e3e'/%3E%3Cstop offset='1' stop-color='%2334a853'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='111' x2='222' y1='254' y2='62' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23fcc934'/%3E%3Cstop offset='1' stop-color='%23fbbc04'/%3E%3C/linearGradient%3E%3ClinearGradient id='c' x1='17' x2='239' y1='80' y2='80' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23d93025'/%3E%3Cstop offset='1' stop-color='%23ea4335'/%3E%3C/linearGradient%3E%3Ccircle cx='128' cy='128' r='64' fill='%23fff'/%3E%3Cpath fill='url(%23a)' d='M96 183a64 64 0 0 1-23-23L17 64a128 128 0 0 0 111 192l55-96a64 64 0 0 1-87 23Z'/%3E%3Cpath fill='url(%23b)' d='M192 128a64 64 0 0 1-9 32l-55 96A128 128 0 0 0 239 64H128a64 64 0 0 1 64 64Z'/%3E%3Ccircle cx='128' cy='128' r='52' fill='%231a73e8'/%3E%3Cpath fill='url(%23c)' d='M96 73a64 64 0 0 1 32-9h111a128 128 0 0 0-222 0l56 96a64 64 0 0 1 23-87Z'/%3E%3C/svg%3E)
- ![Edge: 149.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 27600 27600'%3E%3ClinearGradient id='A' gradientUnits='userSpaceOnUse'/%3E%3ClinearGradient id='B' x1='6870' x2='24704' y1='18705' y2='18705' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%230c59a4'/%3E%3Cstop offset='1' stop-color='%23114a8b'/%3E%3C/linearGradient%3E%3ClinearGradient id='C' x1='16272' x2='5133' y1='10968' y2='23102' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%231b9de2'/%3E%3Cstop offset='.16' stop-color='%231595df'/%3E%3Cstop offset='.67' stop-color='%230680d7'/%3E%3Cstop offset='1' stop-color='%230078d4'/%3E%3C/linearGradient%3E%3CradialGradient id='D' cx='16720' cy='18747' r='9538' xlink:href='%23A'%3E%3Cstop offset='.72' stop-opacity='0'/%3E%3Cstop offset='.95' stop-opacity='.53'/%3E%3Cstop offset='1'/%3E%3C/radialGradient%3E%3CradialGradient id='E' cx='7130' cy='19866' r='14324' gradientTransform='matrix(.14843 -.98892 .79688 .1196 -8759 25542)' xlink:href='%23A'%3E%3Cstop offset='.76' stop-opacity='0'/%3E%3Cstop offset='.95' stop-opacity='.5'/%3E%3Cstop offset='1'/%3E%3C/radialGradient%3E%3CradialGradient id='F' cx='2523' cy='4680' r='20243' gradientTransform='matrix(-.03715 .99931 -2.12836 -.07913 13579 3530)' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%2335c1f1'/%3E%3Cstop offset='.11' stop-color='%2334c1ed'/%3E%3Cstop offset='.23' stop-color='%232fc2df'/%3E%3Cstop offset='.31' stop-color='%232bc3d2'/%3E%3Cstop offset='.67' stop-color='%2336c752'/%3E%3C/radialGradient%3E%3CradialGradient id='G' cx='24247' cy='7758' r='9734' gradientTransform='matrix(.28109 .95968 -.78353 .22949 24510 -16292)' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%2366eb6e'/%3E%3Cstop offset='1' stop-color='%2366eb6e' stop-opacity='0'/%3E%3C/radialGradient%3E%3Cpath id='H' d='M24105 20053a9345 9345 0 01-1053 472 10202 10202 0 01-3590 646c-4732 0-8855-3255-8855-7432 0-1175 680-2193 1643-2729-4280 180-5380 4640-5380 7253 0 7387 6810 8137 8276 8137 791 0 1984-230 2704-456l130-44a12834 12834 0 006660-5282c220-350-168-757-535-565z'/%3E%3Cpath id='I' d='M11571 25141a7913 7913 0 01-2273-2137 8145 8145 0 01-1514-4740 8093 8093 0 013093-6395 8082 8082 0 011373-859c312-148 846-414 1554-404a3236 3236 0 012569 1297 3184 3184 0 01636 1866c0-21 2446-7960-8005-7960-4390 0-8004 4166-8004 7820 0 2319 538 4170 1212 5604a12833 12833 0 007684 6757 12795 12795 0 003908 610c1414 0 2774-233 4045-656a7575 7575 0 01-6278-803z'/%3E%3Cpath id='J' d='M16231 15886c-80 105-330 250-330 566 0 260 170 512 472 723 1438 1003 4149 868 4156 868a5954 5954 0 003027-839 6147 6147 0 001133-850 6180 6180 0 001910-4437c26-2242-796-3732-1133-4392-2120-4141-6694-6525-11668-6525-7011 0-12703 5635-12798 12620 47-3654 3679-6605 7996-6605 350 0 2346 34 4200 1007 1634 858 2490 1894 3086 2921 618 1067 728 2415 728 2952s-271 1333-780 1990z'/%3E%3Cuse fill='url(%23B)' xlink:href='%23H'/%3E%3Cuse fill='url(%23D)' opacity='.35' xlink:href='%23H'/%3E%3Cuse fill='url(%23C)' xlink:href='%23I'/%3E%3Cuse fill='url(%23E)' opacity='.4' xlink:href='%23I'/%3E%3Cuse fill='url(%23F)' xlink:href='%23J'/%3E%3Cuse fill='url(%23G)' xlink:href='%23J'/%3E%3C/svg%3E)
- ![Firefox: not supported.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 512 512'%3E%3Cdefs%3E%3CradialGradient id='ff-b' cx='428.5' cy='55.1' r='501' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23ffbd4f'/%3E%3Cstop offset='.2' stop-color='%23ffac31'/%3E%3Cstop offset='.3' stop-color='%23ff9d17'/%3E%3Cstop offset='.3' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff563b'/%3E%3Cstop offset='.5' stop-color='%23ff3750'/%3E%3Cstop offset='.7' stop-color='%23f5156c'/%3E%3Cstop offset='.8' stop-color='%23eb0878'/%3E%3Cstop offset='.9' stop-color='%23e50080'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-c' cx='245.4' cy='259.9' r='501' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.3' stop-color='%23960e18'/%3E%3Cstop offset='.3' stop-color='%23b11927' stop-opacity='.7'/%3E%3Cstop offset='.4' stop-color='%23db293d' stop-opacity='.3'/%3E%3Cstop offset='.5' stop-color='%23f5334b' stop-opacity='.1'/%3E%3Cstop offset='.5' stop-color='%23ff3750' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-d' cx='305.8' cy='-58.6' r='363' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.3' stop-color='%23ffdc3e'/%3E%3Cstop offset='.5' stop-color='%23ff9d12'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-e' cx='190' cy='390.8' r='238.6' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.3' stop-color='%233a8ee6'/%3E%3Cstop offset='.5' stop-color='%235c79f0'/%3E%3Cstop offset='.7' stop-color='%239059ff'/%3E%3Cstop offset='1' stop-color='%23c139e6'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-f' cx='252.2' cy='201.3' r='126.5' gradientTransform='matrix(1 0 0 1 -48 31)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.2' stop-color='%239059ff' stop-opacity='0'/%3E%3Cstop offset='.3' stop-color='%238c4ff3' stop-opacity='.1'/%3E%3Cstop offset='.8' stop-color='%237716a8' stop-opacity='.5'/%3E%3Cstop offset='1' stop-color='%236e008b' stop-opacity='.6'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-g' cx='239.1' cy='34.6' r='171.6' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23ffe226'/%3E%3Cstop offset='.1' stop-color='%23ffdb27'/%3E%3Cstop offset='.3' stop-color='%23ffc82a'/%3E%3Cstop offset='.5' stop-color='%23ffa930'/%3E%3Cstop offset='.7' stop-color='%23ff7e37'/%3E%3Cstop offset='.8' stop-color='%23ff7139'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-h' cx='374' cy='-74.3' r='732.2' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3Cstop offset='.6' stop-color='%23ff5634'/%3E%3Cstop offset='.7' stop-color='%23ff3647'/%3E%3Cstop offset='.9' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-i' cx='304.6' cy='7.1' r='536.4' gradientTransform='rotate(84 303 4)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23fff44f'/%3E%3Cstop offset='.1' stop-color='%23ffe847'/%3E%3Cstop offset='.2' stop-color='%23ffc830'/%3E%3Cstop offset='.3' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff8b16'/%3E%3Cstop offset='.5' stop-color='%23ff672a'/%3E%3Cstop offset='.6' stop-color='%23ff3647'/%3E%3Cstop offset='.7' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-j' cx='235' cy='98.1' r='457.1' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3Cstop offset='.6' stop-color='%23ff5634'/%3E%3Cstop offset='.7' stop-color='%23ff3647'/%3E%3Cstop offset='.9' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-k' cx='355.7' cy='124.9' r='500.3' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.2' stop-color='%23ffe141'/%3E%3Cstop offset='.5' stop-color='%23ffaf1e'/%3E%3Cstop offset='.6' stop-color='%23ff980e'/%3E%3C/radialGradient%3E%3ClinearGradient id='ff-a' x1='446.9' y1='76.8' x2='47.9' y2='461.8' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.1' stop-color='%23ffe847'/%3E%3Cstop offset='.2' stop-color='%23ffc830'/%3E%3Cstop offset='.4' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff8b16'/%3E%3Cstop offset='.5' stop-color='%23ff672a'/%3E%3Cstop offset='.5' stop-color='%23ff3647'/%3E%3Cstop offset='.7' stop-color='%23e31587'/%3E%3C/linearGradient%3E%3ClinearGradient id='ff-l' x1='442.1' y1='74.8' x2='102.6' y2='414.3' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.2' stop-color='%23fff44f' stop-opacity='.8'/%3E%3Cstop offset='.3' stop-color='%23fff44f' stop-opacity='.6'/%3E%3Cstop offset='.5' stop-color='%23fff44f' stop-opacity='.2'/%3E%3Cstop offset='.6' stop-color='%23fff44f' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M479 166c-11-25-32-52-49-60a249 249 0 0 1 25 73c-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-60 35-81 101-83 134a120 120 0 0 0-66 25 71 71 0 0 0-6-5 111 111 0 0 1-1-58c-25 11-44 29-58 44-9-12-9-52-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73l-1 2-2 15a229 229 0 0 0-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121zM202 355l3 1-3-1zm55-145zm198-31z' fill='url(%23ff-a)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60 14 26 22 53 25 72v1a207 207 0 0 1-206 279c-113-3-212-87-231-197-3-17 0-26 2-40-2 11-3 14-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121z' fill='url(%23ff-b)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60 14 26 22 53 25 72v1a207 207 0 0 1-206 279c-113-3-212-87-231-197-3-17 0-26 2-40-2 11-3 14-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121z' fill='url(%23ff-c)'/%3E%3Cpath d='m362 195 1 1a130 130 0 0 0-22-29C266 92 322 5 331 0c-60 35-81 101-83 134l9-1c45 0 84 25 105 62z' fill='url(%23ff-d)'/%3E%3Cpath d='M257 210c-1 6-22 26-29 26-68 0-80 41-80 41 3 35 28 64 57 79l4 2 7 3a107 107 0 0 0 31 6c120 6 143-143 57-186 22-4 45 5 58 14-21-37-60-62-105-62l-9 1a120 120 0 0 0-66 25l17 16c16 16 58 33 58 35z' fill='url(%23ff-e)'/%3E%3Cpath d='M257 210c-1 6-22 26-29 26-68 0-80 41-80 41 3 35 28 64 57 79l4 2 7 3a107 107 0 0 0 31 6c120 6 143-143 57-186 22-4 45 5 58 14-21-37-60-62-105-62l-9 1a120 120 0 0 0-66 25l17 16c16 16 58 33 58 35z' fill='url(%23ff-f)'/%3E%3Cpath d='m171 151 5 3a111 111 0 0 1-1-58c-25 11-44 29-58 44 1 0 36 0 54 11z' fill='url(%23ff-g)'/%3E%3Cpath d='M18 261a242 242 0 0 0 231 197 207 207 0 0 0 206-279c8 56-20 110-64 146-86 71-169 43-186 31l-3-1c-50-24-71-70-67-110-42 0-57-35-57-35s38-28 89-4c46 22 90 4 90 4 0-2-42-19-58-35l-17-16a71 71 0 0 0-6-5l-5-3c-18-11-52-11-54-11-9-12-9-51-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73c0 1-9 38-5 57z' fill='url(%23ff-h)'/%3E%3Cpath d='M341 167a130 130 0 0 1 22 29 46 46 0 0 1 4 3c55 50 26 121 24 126 44-36 72-90 64-146-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-9 5-65 92 10 167z' fill='url(%23ff-i)'/%3E%3Cpath d='M367 199a46 46 0 0 0-4-3l-1-1c-13-9-36-18-58-15 86 44 63 193-57 187a107 107 0 0 1-31-6 131 131 0 0 1-11-5c17 12 99 39 186-31 2-5 31-76-24-126z' fill='url(%23ff-j)'/%3E%3Cpath d='M148 277s12-41 80-41c7 0 28-20 29-26s-44 18-90-4c-51-24-89 4-89 4s15 35 57 35c-4 40 16 85 67 110l3 1c-29-15-54-44-57-79z' fill='url(%23ff-k)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60a249 249 0 0 1 25 73c-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-60 35-81 101-83 134l9-1c45 0 84 25 105 62-13-9-36-18-58-14 86 43 63 192-57 186a107 107 0 0 1-31-6 131 131 0 0 1-11-5l-3-1 3 1c-29-15-54-44-57-79 0 0 12-41 80-41 7 0 28-20 29-26 0-2-42-19-58-35l-17-16a71 71 0 0 0-6-5 111 111 0 0 1-1-58c-25 11-44 29-58 44-9-12-9-52-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73l-1 2-2 15a279 279 0 0 0-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121zm-24 13z' fill='url(%23ff-l)'/%3E%3C/svg%3E)
- ![Safari: not supported.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='195 190 135 135'%3E%3Cdefs%3E%3ClinearGradient id='s-a' x1='132.6' x2='134.4' y1='111.7' y2='-105.3' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23d2d2d2' /%3E%3Cstop offset='.5' stop-color='%23f2f2f2' /%3E%3Cstop offset='1' stop-color='%23fff' /%3E%3C/linearGradient%3E%3ClinearGradient id='s-b' gradientUnits='userSpaceOnUse' /%3E%3ClinearGradient id='s-c' x1='65.4' x2='67.4' y1='115.7' y2='17.1' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23005ad5' /%3E%3Cstop offset='.2' stop-color='%230875f0' /%3E%3Cstop offset='.3' stop-color='%23218cee' /%3E%3Cstop offset='.6' stop-color='%2327a5f3' /%3E%3Cstop offset='.8' stop-color='%2325aaf2' /%3E%3Cstop offset='1' stop-color='%2321aaef' /%3E%3C/linearGradient%3E%3ClinearGradient id='s-d' x1='158.7' x2='176.3' y1='96.7' y2='79.5' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23c72e24' /%3E%3Cstop offset='1' stop-color='%23fd3b2f' /%3E%3C/linearGradient%3E%3CradialGradient id='s-i' cx='-69.9' cy='69.3' r='54' gradientTransform='matrix(.9 -.01 .04 2.72 -9 -120)' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%2324a5f3' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%231e8ceb' /%3E%3C/radialGradient%3E%3CradialGradient id='s-j' cx='109.3' cy='13.8' r='93.1' gradientTransform='matrix(-.02 1.1 -1.04 -.02 137 -115)' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%235488d6' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%235d96eb' /%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='220' height='220' x='22' y='-107' fill='url(%23s-a)' ry='49' transform='matrix(.57 0 0 .57 187 256)' /%3E%3Cg transform='translate(194 190)'%3E%3Ccircle cx='67.8' cy='67.7' fill='url(%23s-c)' paint-order='stroke fill markers' r='54' /%3E%3Ccircle cx='-69.9' cy='69.3' fill='url(%23s-i)' transform='translate(138 -2)' r='54' /%3E%3C/g%3E%3Cellipse cx='120' cy='14.2' fill='url(%23s-j)' rx='93.1' ry='93.7' transform='matrix(.58 0 0 .58 192 250)' /%3E%3Cg transform='matrix(.58 0 0 .57 197 182)'%3E%3Cpath fill='%23cac7c8' d='M46 192h1l72-48-7-9-66 57Z' /%3E%3Cpath fill='%23fbfffc' d='M46 191v1l66-57-7-9-59 65Z' /%3E%3Cpath fill='url(%23s-d)' d='m119 144-7-9 66-57-59 66Z' /%3E%3Cpath fill='%23fb645c' d='m105 126 7 9 66-57-1-1-72 49Z' /%3E%3C/g%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-miterlimit='1' stroke-width='1.3' d='m287 278 3-2m-12-17 8-2m-8-3h4m-4-13 8 2m-8 3h4m-1-13 7 3m-4-11 7 4m-2-11 6 6m0-12 6 7m1-11 4 6m4-10 3 7m5-9 2 7m15-7-1 7m10-5-3 7m11-4-4 7m11-2-5 6m16 7-7 4m10 4-7 3m10 6-8 1m8 16-8-2m5 10-7-3m4 11-7-4m2 11-6-5m0 11-5-6m-2 11-4-7m-4 11-3-8m-6 10-1-8m-16 8 2-8m-10 5 3-7m-11 4 4-7m-11 2 5-6m-8 3 3-3m4 8 2-3m5 8 2-4m6 7 1-4m8 5v-4m8 4v-4m9 3-1-4m9 1-2-4m9 0-2-4m9-2-3-3m8-4-3-2m8-5-4-2m7-6-4-1m5-8h-4m4-8h-4m3-9-4 1m1-9-4 2m-1-9-3 2m-2-9-3 3m-4-8-2 3m-5-8-2 4m-6-6-1 3m-8-5v4m-8-4v4m-9-2 1 3m-9 0 2 3m-9 1 2 3m-9 2 3 3m-8 4 3 2m-8 5 4 2m-7 6 4 1m-4 25 4-1m-2 5 7-3m-6 7 4-2m-2 6 7-4m-13-21h8m41-41v-8m0 99v-8m49-42h-8' transform='translate(-65 8)' /%3E%3C/svg%3E)

[Source](https://developer.mozilla.org/docs/Web/CSS/Reference/Properties/row-rule)

<br />

[Learn more about CSS Gap Decorations](https://goo.gle/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`.

<iframe src="https:///frame/blog/new-in-web-ui-io26/index_746ab5a42037d1732cc01002d7ece713d1b3a934f24d82d3e6131c9d46ab056c.frame" class="framebox inherit-locale " allow="clipboard-write https://" allowfullscreen is-upgraded></iframe>

[Learn more about scrollbar-aware viewport units](https://goo.gle/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.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='-10 -10 276 276'%3E%3ClinearGradient id='a' x1='145' x2='34' y1='253' y2='61' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%231e8e3e'/%3E%3Cstop offset='1' stop-color='%2334a853'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='111' x2='222' y1='254' y2='62' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23fcc934'/%3E%3Cstop offset='1' stop-color='%23fbbc04'/%3E%3C/linearGradient%3E%3ClinearGradient id='c' x1='17' x2='239' y1='80' y2='80' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23d93025'/%3E%3Cstop offset='1' stop-color='%23ea4335'/%3E%3C/linearGradient%3E%3Ccircle cx='128' cy='128' r='64' fill='%23fff'/%3E%3Cpath fill='url(%23a)' d='M96 183a64 64 0 0 1-23-23L17 64a128 128 0 0 0 111 192l55-96a64 64 0 0 1-87 23Z'/%3E%3Cpath fill='url(%23b)' d='M192 128a64 64 0 0 1-9 32l-55 96A128 128 0 0 0 239 64H128a64 64 0 0 1 64 64Z'/%3E%3Ccircle cx='128' cy='128' r='52' fill='%231a73e8'/%3E%3Cpath fill='url(%23c)' d='M96 73a64 64 0 0 1 32-9h111a128 128 0 0 0-222 0l56 96a64 64 0 0 1 23-87Z'/%3E%3C/svg%3E)
- ![Edge: 149.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 27600 27600'%3E%3ClinearGradient id='A' gradientUnits='userSpaceOnUse'/%3E%3ClinearGradient id='B' x1='6870' x2='24704' y1='18705' y2='18705' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%230c59a4'/%3E%3Cstop offset='1' stop-color='%23114a8b'/%3E%3C/linearGradient%3E%3ClinearGradient id='C' x1='16272' x2='5133' y1='10968' y2='23102' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%231b9de2'/%3E%3Cstop offset='.16' stop-color='%231595df'/%3E%3Cstop offset='.67' stop-color='%230680d7'/%3E%3Cstop offset='1' stop-color='%230078d4'/%3E%3C/linearGradient%3E%3CradialGradient id='D' cx='16720' cy='18747' r='9538' xlink:href='%23A'%3E%3Cstop offset='.72' stop-opacity='0'/%3E%3Cstop offset='.95' stop-opacity='.53'/%3E%3Cstop offset='1'/%3E%3C/radialGradient%3E%3CradialGradient id='E' cx='7130' cy='19866' r='14324' gradientTransform='matrix(.14843 -.98892 .79688 .1196 -8759 25542)' xlink:href='%23A'%3E%3Cstop offset='.76' stop-opacity='0'/%3E%3Cstop offset='.95' stop-opacity='.5'/%3E%3Cstop offset='1'/%3E%3C/radialGradient%3E%3CradialGradient id='F' cx='2523' cy='4680' r='20243' gradientTransform='matrix(-.03715 .99931 -2.12836 -.07913 13579 3530)' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%2335c1f1'/%3E%3Cstop offset='.11' stop-color='%2334c1ed'/%3E%3Cstop offset='.23' stop-color='%232fc2df'/%3E%3Cstop offset='.31' stop-color='%232bc3d2'/%3E%3Cstop offset='.67' stop-color='%2336c752'/%3E%3C/radialGradient%3E%3CradialGradient id='G' cx='24247' cy='7758' r='9734' gradientTransform='matrix(.28109 .95968 -.78353 .22949 24510 -16292)' xlink:href='%23A'%3E%3Cstop offset='0' stop-color='%2366eb6e'/%3E%3Cstop offset='1' stop-color='%2366eb6e' stop-opacity='0'/%3E%3C/radialGradient%3E%3Cpath id='H' d='M24105 20053a9345 9345 0 01-1053 472 10202 10202 0 01-3590 646c-4732 0-8855-3255-8855-7432 0-1175 680-2193 1643-2729-4280 180-5380 4640-5380 7253 0 7387 6810 8137 8276 8137 791 0 1984-230 2704-456l130-44a12834 12834 0 006660-5282c220-350-168-757-535-565z'/%3E%3Cpath id='I' d='M11571 25141a7913 7913 0 01-2273-2137 8145 8145 0 01-1514-4740 8093 8093 0 013093-6395 8082 8082 0 011373-859c312-148 846-414 1554-404a3236 3236 0 012569 1297 3184 3184 0 01636 1866c0-21 2446-7960-8005-7960-4390 0-8004 4166-8004 7820 0 2319 538 4170 1212 5604a12833 12833 0 007684 6757 12795 12795 0 003908 610c1414 0 2774-233 4045-656a7575 7575 0 01-6278-803z'/%3E%3Cpath id='J' d='M16231 15886c-80 105-330 250-330 566 0 260 170 512 472 723 1438 1003 4149 868 4156 868a5954 5954 0 003027-839 6147 6147 0 001133-850 6180 6180 0 001910-4437c26-2242-796-3732-1133-4392-2120-4141-6694-6525-11668-6525-7011 0-12703 5635-12798 12620 47-3654 3679-6605 7996-6605 350 0 2346 34 4200 1007 1634 858 2490 1894 3086 2921 618 1067 728 2415 728 2952s-271 1333-780 1990z'/%3E%3Cuse fill='url(%23B)' xlink:href='%23H'/%3E%3Cuse fill='url(%23D)' opacity='.35' xlink:href='%23H'/%3E%3Cuse fill='url(%23C)' xlink:href='%23I'/%3E%3Cuse fill='url(%23E)' opacity='.4' xlink:href='%23I'/%3E%3Cuse fill='url(%23F)' xlink:href='%23J'/%3E%3Cuse fill='url(%23G)' xlink:href='%23J'/%3E%3C/svg%3E)
- ![Firefox: not supported.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 512 512'%3E%3Cdefs%3E%3CradialGradient id='ff-b' cx='428.5' cy='55.1' r='501' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23ffbd4f'/%3E%3Cstop offset='.2' stop-color='%23ffac31'/%3E%3Cstop offset='.3' stop-color='%23ff9d17'/%3E%3Cstop offset='.3' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff563b'/%3E%3Cstop offset='.5' stop-color='%23ff3750'/%3E%3Cstop offset='.7' stop-color='%23f5156c'/%3E%3Cstop offset='.8' stop-color='%23eb0878'/%3E%3Cstop offset='.9' stop-color='%23e50080'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-c' cx='245.4' cy='259.9' r='501' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.3' stop-color='%23960e18'/%3E%3Cstop offset='.3' stop-color='%23b11927' stop-opacity='.7'/%3E%3Cstop offset='.4' stop-color='%23db293d' stop-opacity='.3'/%3E%3Cstop offset='.5' stop-color='%23f5334b' stop-opacity='.1'/%3E%3Cstop offset='.5' stop-color='%23ff3750' stop-opacity='0'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-d' cx='305.8' cy='-58.6' r='363' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.3' stop-color='%23ffdc3e'/%3E%3Cstop offset='.5' stop-color='%23ff9d12'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-e' cx='190' cy='390.8' r='238.6' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.3' stop-color='%233a8ee6'/%3E%3Cstop offset='.5' stop-color='%235c79f0'/%3E%3Cstop offset='.7' stop-color='%239059ff'/%3E%3Cstop offset='1' stop-color='%23c139e6'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-f' cx='252.2' cy='201.3' r='126.5' gradientTransform='matrix(1 0 0 1 -48 31)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.2' stop-color='%239059ff' stop-opacity='0'/%3E%3Cstop offset='.3' stop-color='%238c4ff3' stop-opacity='.1'/%3E%3Cstop offset='.8' stop-color='%237716a8' stop-opacity='.5'/%3E%3Cstop offset='1' stop-color='%236e008b' stop-opacity='.6'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-g' cx='239.1' cy='34.6' r='171.6' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23ffe226'/%3E%3Cstop offset='.1' stop-color='%23ffdb27'/%3E%3Cstop offset='.3' stop-color='%23ffc82a'/%3E%3Cstop offset='.5' stop-color='%23ffa930'/%3E%3Cstop offset='.7' stop-color='%23ff7e37'/%3E%3Cstop offset='.8' stop-color='%23ff7139'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-h' cx='374' cy='-74.3' r='732.2' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3Cstop offset='.6' stop-color='%23ff5634'/%3E%3Cstop offset='.7' stop-color='%23ff3647'/%3E%3Cstop offset='.9' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-i' cx='304.6' cy='7.1' r='536.4' gradientTransform='rotate(84 303 4)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23fff44f'/%3E%3Cstop offset='.1' stop-color='%23ffe847'/%3E%3Cstop offset='.2' stop-color='%23ffc830'/%3E%3Cstop offset='.3' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff8b16'/%3E%3Cstop offset='.5' stop-color='%23ff672a'/%3E%3Cstop offset='.6' stop-color='%23ff3647'/%3E%3Cstop offset='.7' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-j' cx='235' cy='98.1' r='457.1' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.5' stop-color='%23ff980e'/%3E%3Cstop offset='.6' stop-color='%23ff5634'/%3E%3Cstop offset='.7' stop-color='%23ff3647'/%3E%3Cstop offset='.9' stop-color='%23e31587'/%3E%3C/radialGradient%3E%3CradialGradient id='ff-k' cx='355.7' cy='124.9' r='500.3' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.2' stop-color='%23ffe141'/%3E%3Cstop offset='.5' stop-color='%23ffaf1e'/%3E%3Cstop offset='.6' stop-color='%23ff980e'/%3E%3C/radialGradient%3E%3ClinearGradient id='ff-a' x1='446.9' y1='76.8' x2='47.9' y2='461.8' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.1' stop-color='%23fff44f'/%3E%3Cstop offset='.1' stop-color='%23ffe847'/%3E%3Cstop offset='.2' stop-color='%23ffc830'/%3E%3Cstop offset='.4' stop-color='%23ff980e'/%3E%3Cstop offset='.4' stop-color='%23ff8b16'/%3E%3Cstop offset='.5' stop-color='%23ff672a'/%3E%3Cstop offset='.5' stop-color='%23ff3647'/%3E%3Cstop offset='.7' stop-color='%23e31587'/%3E%3C/linearGradient%3E%3ClinearGradient id='ff-l' x1='442.1' y1='74.8' x2='102.6' y2='414.3' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.2' stop-color='%23fff44f' stop-opacity='.8'/%3E%3Cstop offset='.3' stop-color='%23fff44f' stop-opacity='.6'/%3E%3Cstop offset='.5' stop-color='%23fff44f' stop-opacity='.2'/%3E%3Cstop offset='.6' stop-color='%23fff44f' stop-opacity='0'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M479 166c-11-25-32-52-49-60a249 249 0 0 1 25 73c-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-60 35-81 101-83 134a120 120 0 0 0-66 25 71 71 0 0 0-6-5 111 111 0 0 1-1-58c-25 11-44 29-58 44-9-12-9-52-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73l-1 2-2 15a229 229 0 0 0-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121zM202 355l3 1-3-1zm55-145zm198-31z' fill='url(%23ff-a)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60 14 26 22 53 25 72v1a207 207 0 0 1-206 279c-113-3-212-87-231-197-3-17 0-26 2-40-2 11-3 14-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121z' fill='url(%23ff-b)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60 14 26 22 53 25 72v1a207 207 0 0 1-206 279c-113-3-212-87-231-197-3-17 0-26 2-40-2 11-3 14-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121z' fill='url(%23ff-c)'/%3E%3Cpath d='m362 195 1 1a130 130 0 0 0-22-29C266 92 322 5 331 0c-60 35-81 101-83 134l9-1c45 0 84 25 105 62z' fill='url(%23ff-d)'/%3E%3Cpath d='M257 210c-1 6-22 26-29 26-68 0-80 41-80 41 3 35 28 64 57 79l4 2 7 3a107 107 0 0 0 31 6c120 6 143-143 57-186 22-4 45 5 58 14-21-37-60-62-105-62l-9 1a120 120 0 0 0-66 25l17 16c16 16 58 33 58 35z' fill='url(%23ff-e)'/%3E%3Cpath d='M257 210c-1 6-22 26-29 26-68 0-80 41-80 41 3 35 28 64 57 79l4 2 7 3a107 107 0 0 0 31 6c120 6 143-143 57-186 22-4 45 5 58 14-21-37-60-62-105-62l-9 1a120 120 0 0 0-66 25l17 16c16 16 58 33 58 35z' fill='url(%23ff-f)'/%3E%3Cpath d='m171 151 5 3a111 111 0 0 1-1-58c-25 11-44 29-58 44 1 0 36 0 54 11z' fill='url(%23ff-g)'/%3E%3Cpath d='M18 261a242 242 0 0 0 231 197 207 207 0 0 0 206-279c8 56-20 110-64 146-86 71-169 43-186 31l-3-1c-50-24-71-70-67-110-42 0-57-35-57-35s38-28 89-4c46 22 90 4 90 4 0-2-42-19-58-35l-17-16a71 71 0 0 0-6-5l-5-3c-18-11-52-11-54-11-9-12-9-51-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73c0 1-9 38-5 57z' fill='url(%23ff-h)'/%3E%3Cpath d='M341 167a130 130 0 0 1 22 29 46 46 0 0 1 4 3c55 50 26 121 24 126 44-36 72-90 64-146-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-9 5-65 92 10 167z' fill='url(%23ff-i)'/%3E%3Cpath d='M367 199a46 46 0 0 0-4-3l-1-1c-13-9-36-18-58-15 86 44 63 193-57 187a107 107 0 0 1-31-6 131 131 0 0 1-11-5c17 12 99 39 186-31 2-5 31-76-24-126z' fill='url(%23ff-j)'/%3E%3Cpath d='M148 277s12-41 80-41c7 0 28-20 29-26s-44 18-90-4c-51-24-89 4-89 4s15 35 57 35c-4 40 16 85 67 110l3 1c-29-15-54-44-57-79z' fill='url(%23ff-k)'/%3E%3Cpath d='M479 166c-11-25-32-52-49-60a249 249 0 0 1 25 73c-27-68-73-95-111-155a255 255 0 0 1-8-14 44 44 0 0 1-4-9 1 1 0 0 0 0-1 1 1 0 0 0-1 0c-60 35-81 101-83 134l9-1c45 0 84 25 105 62-13-9-36-18-58-14 86 43 63 192-57 186a107 107 0 0 1-31-6 131 131 0 0 1-11-5l-3-1 3 1c-29-15-54-44-57-79 0 0 12-41 80-41 7 0 28-20 29-26 0-2-42-19-58-35l-17-16a71 71 0 0 0-6-5 111 111 0 0 1-1-58c-25 11-44 29-58 44-9-12-9-52-8-60l-8 4a175 175 0 0 0-24 21 210 210 0 0 0-22 26 203 203 0 0 0-32 73l-1 2-2 15a279 279 0 0 0-4 34v1a240 240 0 0 0 477 40l1-9c5-41 0-84-15-121zm-24 13z' fill='url(%23ff-l)'/%3E%3C/svg%3E)
- ![Safari: not supported.](data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='195 190 135 135'%3E%3Cdefs%3E%3ClinearGradient id='s-a' x1='132.6' x2='134.4' y1='111.7' y2='-105.3' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23d2d2d2' /%3E%3Cstop offset='.5' stop-color='%23f2f2f2' /%3E%3Cstop offset='1' stop-color='%23fff' /%3E%3C/linearGradient%3E%3ClinearGradient id='s-b' gradientUnits='userSpaceOnUse' /%3E%3ClinearGradient id='s-c' x1='65.4' x2='67.4' y1='115.7' y2='17.1' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23005ad5' /%3E%3Cstop offset='.2' stop-color='%230875f0' /%3E%3Cstop offset='.3' stop-color='%23218cee' /%3E%3Cstop offset='.6' stop-color='%2327a5f3' /%3E%3Cstop offset='.8' stop-color='%2325aaf2' /%3E%3Cstop offset='1' stop-color='%2321aaef' /%3E%3C/linearGradient%3E%3ClinearGradient id='s-d' x1='158.7' x2='176.3' y1='96.7' y2='79.5' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%23c72e24' /%3E%3Cstop offset='1' stop-color='%23fd3b2f' /%3E%3C/linearGradient%3E%3CradialGradient id='s-i' cx='-69.9' cy='69.3' r='54' gradientTransform='matrix(.9 -.01 .04 2.72 -9 -120)' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-color='%2324a5f3' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%231e8ceb' /%3E%3C/radialGradient%3E%3CradialGradient id='s-j' cx='109.3' cy='13.8' r='93.1' gradientTransform='matrix(-.02 1.1 -1.04 -.02 137 -115)' xlink:href='%23s-b'%3E%3Cstop offset='0' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%235488d6' stop-opacity='0' /%3E%3Cstop offset='1' stop-color='%235d96eb' /%3E%3C/radialGradient%3E%3C/defs%3E%3Crect width='220' height='220' x='22' y='-107' fill='url(%23s-a)' ry='49' transform='matrix(.57 0 0 .57 187 256)' /%3E%3Cg transform='translate(194 190)'%3E%3Ccircle cx='67.8' cy='67.7' fill='url(%23s-c)' paint-order='stroke fill markers' r='54' /%3E%3Ccircle cx='-69.9' cy='69.3' fill='url(%23s-i)' transform='translate(138 -2)' r='54' /%3E%3C/g%3E%3Cellipse cx='120' cy='14.2' fill='url(%23s-j)' rx='93.1' ry='93.7' transform='matrix(.58 0 0 .58 192 250)' /%3E%3Cg transform='matrix(.58 0 0 .57 197 182)'%3E%3Cpath fill='%23cac7c8' d='M46 192h1l72-48-7-9-66 57Z' /%3E%3Cpath fill='%23fbfffc' d='M46 191v1l66-57-7-9-59 65Z' /%3E%3Cpath fill='url(%23s-d)' d='m119 144-7-9 66-57-59 66Z' /%3E%3Cpath fill='%23fb645c' d='m105 126 7 9 66-57-1-1-72 49Z' /%3E%3C/g%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-miterlimit='1' stroke-width='1.3' d='m287 278 3-2m-12-17 8-2m-8-3h4m-4-13 8 2m-8 3h4m-1-13 7 3m-4-11 7 4m-2-11 6 6m0-12 6 7m1-11 4 6m4-10 3 7m5-9 2 7m15-7-1 7m10-5-3 7m11-4-4 7m11-2-5 6m16 7-7 4m10 4-7 3m10 6-8 1m8 16-8-2m5 10-7-3m4 11-7-4m2 11-6-5m0 11-5-6m-2 11-4-7m-4 11-3-8m-6 10-1-8m-16 8 2-8m-10 5 3-7m-11 4 4-7m-11 2 5-6m-8 3 3-3m4 8 2-3m5 8 2-4m6 7 1-4m8 5v-4m8 4v-4m9 3-1-4m9 1-2-4m9 0-2-4m9-2-3-3m8-4-3-2m8-5-4-2m7-6-4-1m5-8h-4m4-8h-4m3-9-4 1m1-9-4 2m-1-9-3 2m-2-9-3 3m-4-8-2 3m-5-8-2 4m-6-6-1 3m-8-5v4m-8-4v4m-9-2 1 3m-9 0 2 3m-9 1 2 3m-9 2 3 3m-8 4 3 2m-8 5 4 2m-7 6 4 1m-4 25 4-1m-2 5 7-3m-6 7 4-2m-2 6 7-4m-13-21h8m41-41v-8m0 99v-8m49-42h-8' transform='translate(-65 8)' /%3E%3C/svg%3E)

[Source](https://developer.mozilla.org/docs/Web/API/Element/pseudo)

<br />

<iframe height="600" style="width: 100%;" scrolling="no" title="CSSPseudoElement Interface Demo" src="https://codepen.io/web-dot-dev/embed/XJNKXMG?default-tab=result" frameborder="no" loading="lazy" allowtransparency="true">
See the Pen <a href="https://codepen.io/web-dot-dev/pen/XJNKXMG">
CSSPseudoElement Interface Demo</a> by web.dev (<a href="https://codepen.io/web-dot-dev">@web-dot-dev</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>

[Learn more about `CSSPseudoElement`](https://goo.gle/csspseudoelement-explainer)

## 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!