Modern UI Patterns
Introduction and the AI Elephant in the Room
Una is introduced as a CSS Working Group member and Chrome DevRel engineer. She opens by acknowledging AI as the defining challenge facing the web industry, prompting her to rethink not just how to build modern UI patterns, but what to build and why — shifting focus toward the quality and purpose of user experiences.
Five Key UX Principles for Premium Web Experiences
Una outlines her journey from engineering back toward design thinking, describing how she worked with UX researchers to define five principles for high-quality web experiences: respecting user preferences, reducing noise, implementing natural interactions, providing guided navigation, and adapting to form factor. She argues the web already has the tools to match app-quality experiences.
Respecting User Preferences: Advanced Color Theming
Una explores deep theming techniques beyond basic prefers-color-scheme, including a custom CSS light-dark function using custom properties and style queries to enable font-weight switching without native color-scheme support. She then demonstrates the newly cross-browser contrast-color function and shows how combining it with style queries enables fully dynamic, personalized macro and micro color theme systems.
Reducing Noise: Scroll State Queries and the Hidey Bar
Una introduces the principle of reducing interface noise, illustrating how obtrusive banners can consume nearly 40% of screen real estate. She demonstrates the 'hidey bar' pattern — a header that disappears on scroll and reappears on scroll-up — built with scroll state queries instead of JavaScript. She also showcases a navigation shrinking pattern by Z Hassan that uses scroll state to collapse icons into dots for a more refined experience.
Scroll-Driven and Scroll-Triggered Animations
Una covers scroll-driven animations as a tool for progressive enhancement, highlighting examples of animated headers and a lesson-plan app that reveals detail as the user scrolls deeper. She notes scroll-driven animations are becoming an interop priority and introduces the newly landed scroll-triggered animations in Chrome 146 as a complementary capability.
Layered UI: Popovers, Anchor Positioning, and Tooltips
Una examines layered UI patterns and how the popover API handles semantics, focus management, light-dismiss, and viewport collision for free. She walks through building polished tooltips with CSS triangle connectors, anchor positioning with fallback flipping, and container queries to keep visual connector arrows properly oriented when popovers flip direction. She also introduces the border-shape property as a modern alternative for geometric tooltip arrows.
Interest Invokers: Hover Tooltips and Accessibility Trade-offs
Una introduces the interest invoker API, which opens popovers on hover, keyboard focus, or long-press on mobile. She walks through implementation on her own blog's internal links as a progressive enhancement, shares UX tips on tuning the interest-delay-start for snappiness, and demonstrates stacking multiple popovers on one element. She then raises an open standards debate about the interest button pseudo-element default on touch devices, arguing it should be opt-in rather than a blanket default.
Natural Interactions: Animations, Morphing, and View Transitions
Una covers techniques for making interfaces feel alive and responsive: button press scaling, motion blur approximation with Gaussian blur, spring-like easing with the linear function, and staggered animations using sibling-index. She showcases morphing with scoped view transitions in Chrome 147, demonstrating a feedback button morphing into a form and a copy-to-clipboard icon fade, and shows how directional view transitions can animate counter values up or down to reflect meaningful state changes.
Adapting to Form Factor: Touch Gestures and Swipe Patterns
Una addresses the gap between desktop development and mobile experience, arguing it contributes to the web feeling janky. She demonstrates swipe-to-close menus built with scroll snapping and overscroll areas as a CSS/HTML-native gesture API her team is actively developing. She closes with a rallying call to raise expectations for the web, use its modern capabilities, and focus on the 'little big things' that make experiences feel human and premium.
Q&A: Reduced Motion, Tooltip Flipping, and Scroll State Queries
The host fields audience questions for Una. Topics include how to handle prefers-reduced-motion without eliminating animation entirely, whether anchor positioning should auto-flip tooltip properties, whether has-interest-source has an equivalent for click popovers (answered: popover-open), and how scroll-state scroll-bottom and scroll-top can be combined to persist or toggle styles based on scroll direction.
So any cool CSS feature that you have seen recently have almost certainly been touched by them. You have very likely seen their wonderful demos they do for work, but her passion goes beyond that. From podcast, videos, talks, and their own blog, she's a pillar of our CSS community and a member of the CSS working group, the Open UI community group, and representing the Google Google Chrome team, our sponsors. Yuna. Give a round of applause, please.
Thank you. Wow. Thank you. Hi, everyone. How are you feeling? Yeah. This is an awesome event. I feel so grateful to be here on this stage in front of some of my heroes in this industry, and I'm gonna talk to you today about modern UI patterns. There's gonna be lots of modern CSS tips and tricks, but I really wanna think about user experience in this talk.
So let's talk about the elephant in the room, which no one has talked about yet on stage. It's, you know, that which must not be named. It's AI. This is something that is happening to our industry. There is so much change right now, and that change is scary. I've really been thinking about what does this mean for us as developers? What does it mean for us as creatives?
What does it mean for us as people who love the web ecosystem and love this community? And I've really been digging into this. Like, you know, what do people care about today? How does this affect what we do, how we build? And I feel like this has really, had me thinking about, you know, why do I come up here on stage and and give these talks? You know, I used to talk a lot about how to build modern UI patterns, how you can reduce your, scripting workload, how you can make things more efficient and performant.
But I think it's really important to understand how to build. In today's era, I think it's almost more important to know what to build or even why you're making the decisions that you're making when you are building. And so this is what I wanna drive today a little bit, a conversation about how do you know when you're making a really high quality web experience?
How can you measure that? How do you know that what you're making is going to have a great user experience for somebody else? And for me, I feel like this was a bit of a journey that I've gone on recently where I have a background in design and development, but throughout my career, I've really been focusing a lot more on the engineering side of it and a lot less on the design thinking and interaction design side of it.
So this was a challenge for me where I wanted to dig into what does this mean? What is a good user experience? And so I started going in a bit of a exploration myself, really following a lot of interaction designers, design engineers, folks who I don't already have as a part of my community. Because there's a lot of folks here who I learn from every day. I remember seeing Lia Vru on stage in 2012 in Prague, and I was like, oh, that's so cool.
Front end is awesome. I wanna do that. I wanna dig in there. Like, I learned so much from Adam and Bramis, and a lot of the people are sitting here today and were on stage today. You know, I'm not gonna name every single name, but honestly, so many of you have really, created this industry and impacted it so much. But I wanted to dig beyond that and people who weren't already in my circle.
So I started exploring what does that look like. And here are just some of the design engineers and tools that I've been looking into. I took a course by Miel Kowalski. I've also been working with our UX research team and trying to figure out, like, how do you define a quality user experience? What makes a web experience feel premium?
So we've identified these five key UX principles that kind of outline, this journey. And so the first one is really about respecting user preferences. I'll I'll dig into all of these. The second is about really maximizing content and reducing noise, simplifying the user experience. The third is all about implementing natural interactions where you can. The fourth is guiding your user, providing guided navigation in this digital space, which is hard to navigate.
It's just a flat screen. And the fifth is really adapting to the form factor from which your user is using your site. So this all lets you create more Appy experiences. And I feel like we have sort of, as a web community, have accepted that the web is just a little bit jankier than an app. And it does not have to be that way because we have the tools.
We have the web capabilities. We've shipped so many great things to the browser that we can build better on the web. Yeah. We can. So the first point is all about respecting user preferences, and, that includes things like theming and motion, thinking about the user's context, so time, place, light levels, letting the user really codesign the experience with you.
I used to give a talk about, this idea of the new responsive and different vectors and axises of what responsive design really means. And this is really about the user being a part of the design journey and designing with you, being responsive to the user. So I know that we're all familiar with, you know, preference queries, first color scheme, we learned a lot about today, first contrast, first reduced motion when you have animation, first reduced transparency.
We all do this. Right? Right? We all do this. Okay. Good. Just checking. And we learned yesterday too from Sarah's great talk all about theming and, first color scheme with light dark. But I'm gonna show you some fun little tips and tricks on how you can leverage this to go even deeper with with these capabilities. So just as a quick recap, first, have to set your color scheme. You can have dark.
You can have light. You can set color values with light dark. So you could here, I'm changing, the background to light pink, or I could have it black when it's dark. You can do things like this, like changing the color of that title from purple to white. But what you can't do is this. Like, this is not a thing.
You can't do something like seven hundred and four hundred for the font weight. And so as we learned yesterday, color scheme would enable this capability. But luckily, while we don't have color scheme in every browser, I do work with some smart people who found a way around this without the requirement for color scheme that you can use today in some browsers and hopefully others soon.
This is Brahmas, who you saw speak yesterday, and this is my favorite photo of him from last time he was on the stage. So you can use CSS custom functions. And please upvote because I feel like there's so much utility with functions and especially if. But what you essentially do is you create a couple of on off values, right, some Boolean values.
So you would have in your root value this scheme custom property. You can name it anything you want. You would essentially set it to light at first, and then you would have your prefers color scheme media query here where you would update the scheme to dark when you had the preference media created. So now you can target these custom properties that you created in your function. You can create add function, create your own custom light dark function, so dash dash light dark.
You have your light value. You have your dark value. And the result would be if we've we've seen a lot of style create demos here too. If the style query is dash dash scheme dark, then set this value to the dark value. Else, set it to the light value. So the usage is very similar to the light dark function, but it's your own custom light dark function where you can set 700 or 400 and actually use this today in a browser where you could, you know, change the color scheme here from dark to light.
And then in this little iframe, I have that applying to, this little text here where it's gonna be a thicker font weight. So cool. That's a fun fun start. But we can get even deeper with contrast color, which recently landed in all stable browsers with Chrome being the latest to implement this. And I think that this opens even more doors for color theming for us. So the simple usage is you first would have some kind of color that you're testing against.
In this case, I'm testing against the button background color, and then I'm going to set the color on the button to button background, using contrast color to get a value back that's either black or white. So it's gonna be testing against this button background. Here, you could see it's, white on the maroon. It's gonna be, black on the yellow.
Again, darker values, you're gonna see white. And then lighter values, you see black. So this is a great start, but it is also very limited. You only get white or black. However, we can leverage this like a boolean value and then use that to create any color scheme we want and color theme we want. So in order to do this, we'd first have to create a custom property, contrast color, give it a syntax, initial value, and then we can actually leverage this value, use contrast color against a background here. And once we do that, we can set that to the variable contrast color.
We're gonna get either black or white, but then we can use that with style queries to say, if the style of contrast color is white, set this to lemon chiffon instead of white or whatever color you wanna pick. Else in a dark theme, if that color is black, set it to indigo. So this gives us the ability to create any kind of theme system we want.
You do have to test all the color yourself. Right now, the contrast color function uses the WCAG two contrast algorithm, which there's a possibility that'll expand in the future, but for now, it's limited to that contrast algorithm, and it's limited to just black and white. But you can try this out yourself, do the testing yourself. If you're unhappy also with some of those middle ground colors, you can create your own color systems and make this really dynamic.
So, we can take that even a step further, and you can use things like light dark for things that aren't just color by, using a little bit of clever transparency. So in this case, I wanted to have like a neon glowy border on a dark background and a subtle little shadow on a light background. Like, this is a common thing that design systems will do to make cards sort of stand out from their page.
And so we can leverage light dark giving us, you know, first value in a light theme or second value in a dark theme by using transparent. So we have this box shadow, which has six values, but only the first three are visible in a light theme, and only the second three are visible in a dark theme. So what we can do with this is set box shadow to light dark, give it a color value.
So in a light theme, looks like this. You've got your shadow defined here, and then, it'll be transparent for the sort of inset glowy border on a light theme. And then when we set it to a dark theme, we sort of get the opposite where you don't see that gray shadow because, well, you wouldn't really see it anyway.
It might be kinda awkward depending on the color you used. And then we're using, relative color syntax to create this, like, a neon glow that uses the color value from the card background itself. So this is kind of how I'm imagining the future of color theming. And, you know, I'll tell you a secret. This actually works on all browsers today.
So I tested this in Safari. Tested it in Firefox, but because you don't really need at function and if for this, you can just do this with style queries, light, dark, and contrast color. You can do this entire color theming system today. It is baseline newly available, and I've had a blog post in my drafts for, like, three months.
I've been waiting for style queries to ship and then had a bunch of events. So I owe you a blog post, but this is possible today. The future is now. We can really create these these personalized color themes with these, like, micro themes and macro themes. The macro theme being, do you have, you know, what's the color of the page? How do you do your shadows?
And the micro theme will be, like, you know, I'm in a dark theme, but not every card is gonna have light text. You might have a card with dark text because it's a lighter card on a darker theme and vice versa on the light theme. So this gives you a lot of different permutations and a lot of control over what you can do for theming.
Oh, no. What's that? Okay. Subscribe. I don't want to subscribe. Let's oh. Hold Hold on. Sometimes I can actually click on this. If I click, it'll change to the next slide. This doesn't always work, but sometimes this is like when I'm bored and rehearsing the deck. I'm like, oh, little mini game. That's a pro tip for speakers.
Create mini games inside of your decks. Okay. I'm not getting it today, but I did get it earlier. So the second principle is reducing noise because we all hate these obtrusive pop ups and banners that obscure the screen, ask you for your newsletter, eliminate visual clutter and application borders, and keep the interface clean and focused. So here's an example of a web experience that frustrates me. First, when you go to any website, it's like, hey.
Download our app immediately. I don't wanna download a bunch of apps. I wanna use this on the web. So I wanna close that. And then this one, this is Google Photos. There was, like, a big banner, and then underneath the banner, there's also, like, a secondary action bar. And these don't go away when you scroll. They don't go away.
They just sit there. And I was like, how much space is actually taking up on the screen? And it turns out it's almost 40% of the entire screen real estate on my new fancy iPhone is covered by these borders, which is very frustrating. But, actually, we're in the EU, so let me make you feel more at home. It looks more like this first, and then you see most of your screen covered up by obtrusive borders and hunters.
So we can fix this with a couple of lines of CSS, and this is a pattern that I love because it's a really great progressive enhancement. I use this as a progressive enhancement on my site without changing the current experience. So this is called a hidey bar. As you scroll, it goes away. And then when you start to scroll up, it comes right back.
And you used to have to do a lot of annoying JavaScript to do this. Now all you need are scroll state queries. Oh, who here has heard of scroll state queries? Who here has used them? Okay. A couple people. Scroll state queries are awesome. And if I would have any wish list, also, that's for browser vendors here. Heard there's a couple of browser vendors here.
Scroll state queries are just they enable so many awesome experiences on the web. Adam Argyle, my former colleague, did so much work on scroll state queries and really has some great articles and talks about them. But there are a couple of different scroll state queries. There's stuck for when something is in a sticky state. There's snapped for when things are moving into a snapped position, like, for example, in a carousel.
There's a scrollable state query when something has scrolls, so you can do scroll indicators. And then there's scroll state scroll, which is the newest one to ship in, it's currently Chrome only, but I'm gonna show you a couple of progressive enhancements that you can do with it. And this lets you identify scroll direction and if there has been a scroll. This one is awesome.
So first, you'd have to set up your container query with container type scroll state, and that's gonna be on my HTML because I wanna set this on the entire page. Right? Then we can do a couple of things. So first, the way that my page on my, blog was organized is I had a header, and it was positioned relative next to the rest of my page, like the main part of my page, the nav and the main body.
So right now, if you're on the site and you're in non supported browser, you would just have to scroll all the way back to the top to see the header. I didn't wanna change the architecture of this at all. I didn't wanna have any kind of weird, experience for unsupported browsers because right now it's only in one browser engine.
So I updated this from relative to sticky when a scroll began. So that's what I'm do oh, that's what I'm doing here. What I'm doing is I'm setting at container once we've set up the container here. And then I'm using scroll state scrolled none to essentially say there has not been a scroll yet. Then I can negate that with not.
And so if there hasn't not been a scroll, that means there has been a scroll. Right? So then I'm gonna convert this to position sticky. I'm gonna give it a position at the top and then give it this trans transition of translate and give it time. Alright. So that's the first step. So now once there has been a scroll, it's gonna be position sticky. Then I'm gonna be using scroll state scrolled bottom so that when I scroll towards the bottom, I'm translating this up zero negative a 100% so it's outside of the viewports.
And when I scroll back upward to the top with scroll state scroll top, then I'm gonna translate this back to zero zero at the top of the page. This So is a way that we can start to leverage some of these modern features to enable these better UX patterns without changing the current user experience or degrading it in any way.
So I really, really love scroll state queries. And as I was exploring this a little bit more too, I really like this pattern from a z Hassan where on his personal blog, he was exploring also these just really cute icons. But as you scroll down, we're not completely getting rid of this navigation bar. We're kind of shrinking it to make more room in that little section as you're scrolling.
And this can also be done in the same way using at container scroll state scrolled. As you're scrolling to the bottom, what we're gonna do is essentially change this from the SVG view to a little dot view. So add a little bouncy animation, and it just, like, feels a lot more premium. It feels like a lot more of a quality thought through UI that a human really created and thought about.
So you can also do this with scroll driven animation, which is going to be interop this year. Right? Yes? Okay. Good. I'm seeing some head shaking. This enables so many great experiences on the web, you know, entire page transitions and scroll driven animations, also smaller effects. What I really liked also was this example from Oscar Poweka of this sort of progressive app.
So, like, as you scroll, you might be at the top and you wanna see an overview of, you know, this is like a lesson plan here. But as you scroll down, you might wanna drill into more details and tips and sources. And so I like the thinking behind this, what you see as you engage more with the app as you're entering into this app space more. And I I feel like that's a good example.
This is another one from BrahMis where as you scroll, you can just add these different animations to different parts of the header. And so, you know, you might have adjust info or shrink the name or add the shadow to the header. And here, we're just leveraging scroll driven animations with the animation timeline of scroll between, zero and a 150 pixels.
As So you're scrolling, we're sort of seeing these things move. And again, exciting that this is going to be available in all browsers soon soon. One newer feature that just landed in Chrome one forty six is scroll triggered animations. And I think that this is something that we all have seen on the web. We've won this on the web.
It lets you create time based animations that trigger at a scroll point and lets you leverage the viewport to set up this animation. So that's that's gonna be awesome to see take off in the future. So another way to sort of minify your UI or really focus on the most important things is by leveraging layered UI and layered UI patterns on top of the rest of your page.
But there are a lot of considerations to get right with layered UI. Like, you gotta get the semantics right. You gotta get the visual design. Think about what that looks like, the interactions, right, like how you're animating in the layered UI, how is it responsive to the rest of the page UI. So there's a lot of considerations here, and popover helps us with a lot of those.
Like, it helps us with a lot of the affordances and the experiences that you used to have to do a lot of scripting to enable. You get free light dismiss. You get the escape key bindings. You get the focus management. And we learned about popover yesterday in Jake's talk, which was an excellent talk. And so, you know, you get also just this, like, collision with the viewport just basically for free with just position, try, flip, block. So let's take a look at some of the design of this. Right? So one thing that, you almost always wanna do with tooltips is create some kind of visual indicator connector between the invoker, which in this case is this button, and the, popover itself.
So the way that we often create CSS triangles today, it's a bit of a hack, but it is by doing a border with most of it being transparent and either the top or the bottom or a piece of it getting a color. So the border top color here would be the same as the tooltip background that I wanna do.
So we can create that. I've position area this, given it a position area at the top. And then when this is flipping to the other direction, we have to keep taking into account, what about that little connector visual? So if I don't do this, you know, you can imagine that as this is gonna flip, this is gonna stay at the bottom.
And you just have this whole thing translated. And that's not what you want. So we can use a container query, an anchored container query, with anchored fallback flip block because I'm letting the browser do it for me. And you can also bring your own position areas. You can bring your own, custom positions. But in this case, I'm just gonna set that container, anchor it, fallbackflip block, and then I'm gonna change the position area of the tooltip itself. But, also, I'm gonna update the border top color and border bottom color to redesign or style this little triangle.
And then lastly, something that Jake had mentioned in his talk was one nice thing about these, tooltips is that as you move, you know, you kinda can get this effect where they stay on the screen. And if you have something like this, like, visual little triangle, you also have to keep that into account. So what you can do is create another anchor on the button, give it an anchor name.
This will be an explicit anchor and calling it invoker, and then set the position anchor of invoker on that little before pseudo element with the triangle. That way, it's going to be connected to an anchor to and following the invoker as you move throughout your design. There's also another new capability in town called border shape.
We also just learned about shape from Eric's talk. If you actually look at the code here, it looks crazy, and I am not him. I can't read this. But this essentially is a way to write directionality. Right? So you have your shape. You can use custom properties in here, which I'm doing. I have the direction, the arrow's height, the width.
Also, I'm updating the corner radius here. You can move the position. You can flip this to the top to the right. Like, I I built a little mini tool for myself so I can just get the output that I wanted to create the demo. But you can use shape within border shape to also create new, geometric UI for your elements.
It doesn't have to all be boxes and divs these days. And what's really cool about this is, like, you get all of the built in features that you would expect of something that follows the shape of your UI. So even if I toggle this, like, this is real inset and outset UI, and, like, shadows follow it. You don't need clip mask, which would hide the shadows.
You can have outlines and focus. And this goes way beyond something you can do with quarter shape. Like, you can make the shape any way you want. You saw the, tool from Temeni Afif also in Eric's talk. Temeni's done so much cool stuff with shape, and it's just so exciting to see. So anyway, is a powerful feature.
This is another way that you can create that little visual sort of anchor arrow when you're creating tooltips. But another thing you have to think about too is how are you transforming and animating. Right? So we just don't want to appear. So first, you're going to have your content. You're going to have your animation. You're going to have your border shape, which I'm just going to give it a variable, but it's going to look like that CSS output earlier. And then a transform origin, and this is gonna animate up. So if we are opening this where the tooltip is animating up, we're gonna have an animation where it's going sort of translating up a little bit and having some opacity come in.
And the opposite is gonna happen when it's animating down. So we're gonna update the animation name in this anchored container query, update the shape, update the transform origin, all the all the good stuff that we want as we are, you know, thinking about these details of the UI. There's a lot of considerations. So this is where I wanna talk about interest invokers.
Has anyone here heard of interest invokers? Okay. Got a couple, but a lot of people haven't. Have you ever seen, you know, a hover invoke tooltip? Have you ever been on social media or GitHub or literally anywhere on the entire web has these? So interest invoking is essentially opening up a popover or an element based on interest. And so that means either a hover effect or on keyboard if you tap into it.
Or right now on mobile devices, when you use this API, if you do a long press, it'll appear in the context menu. This is an API that, is currently going through a bit of discussion. It is shipped currently in Chrome. There might be some changes. But this is a way to get a lot of complex behavior, and especially getting the accessibility of these things right.
Like, this behavior is really complex. I we talked to a lot of teams at big companies who said they spent like six months with a team of three engineers full time trying to get this right. And then they weren't even sure if they got the accessibility right. So there's been so much work that was done in Open UI and in what working group and in CS's working group to make sure that we're landing a lot of these components right.
And this is one of those that has particularly challenging design. So interest invokers work with interest four instead of popover target or command invoker. You And do the same thing where you hook it up to the ID of the popover. This could be a regular auto popover. It could be a different type of popover like hint. But, yeah, you can open them.
So like I said, not available cross browser yet. There is a polyfill available for the interaction on on keyboard and on mouse. The polyfill does not work on the mobile long press interaction. So you can use these what's interesting is not just with buttons, but also with links. So in this example, I'm currently now adding these to all of my internal links on my site.
Because, like, as I start writing talks, I just, like, wanna make more demos and do things and do more projects. So I've got it up here open. But in this example, I've got this link where I have, this contrast color piece of text and then a link where it goes to internal blog. And then I'm giving it an interest for, giving that a name. And then at the end of my document, I'm gonna have my popovers.
This is the popover hint, it doesn't close other popovers that are open. I'm connecting with an ID. And then I can have just like all of the content that I want in there. And this is also like as I scroll, gonna move around and, adjust. So this is another progressive enhancement where currently the experience on my site isn't going to change.
If you're reading my blog, you see a link, it'll look the exact same. But if you have a, a browser that does support interest invokers, you'll be able to either tab or hover over it and see a little bit of a link preview, which I think is cool. I'm all about progressive enhancement. A couple of UX pro tips for using interest invokers.
The default user agent style is zero point five seconds, but I think that's a little bit slow. And, also, this is a tip from Emil Kowalski who, had mentioned, like, hey. If you're already interacting with an action bar, you don't wanna delay on every single item. And that's the default. So you just wanna delay maybe initially so you don't initially accidentally trigger the interest invoker.
But then you might wanna update that to zero so it feels very snappy. Sometimes the best animation is no animation or fast animation, a minimal animation. So you can do this also with, you know, some CSS. It's pretty, pretty easy to do. One line code. Love that. But what we're looking for here is if the parent has something that has interest, which is has interest source, then on the interest invokers, update the interest delay start to zero point five seconds.
Just remove it. So that's, like, one way that you can implement this kind of pattern, one of those little big things that I think really makes a difference in our UIs. You can also do, multiple popovers on the same element. So this is an example, from YouTube where you have these two little icon buttons. You have tooltips, but you can also click through and see this popover show up with notifications.
You might have rich content in there. And the reason why it's not closing when this other little tooltip opens is because that is a hint popover, and that essentially says, don't close other popovers while I'm open. So you can have multiple popovers appearing on the same button. So in this case, I've got the popover target for the actual auto popover, which is notifications, div, which would have the notifications, and then also an interest for for this little tool tip for notifications.
So you can, like, multistack things and have multifunctional popovers. Last year at CSS Day, we talked about this, and we talked about one of the big challenges in implementing this API, which was, well, what do you do on touch devices? We presented a couple of examples and ideas, and ultimately, we settled on this idea of an interest button pseudo element where you would be able to, get a visual representation of, like, that little eye.
That's what it looks like today, which if you clicked on it, would open the interest invoker. So this is the current solution for interest invokers. But if you look at something like this, like, was added to Canary, and I I opened my demos. I was like, that doesn't look good. Oh, we're gonna ship that like that? And then, you know, I'm thinking about, well, what about toolbars that are even more complex?
Like, this is the Google Docs toolbar where you might even have, like, a submenu. And can you imagine having a separate icon that shows that there's an interest invoker after every single one of those, like, just for a little tool tip? And, you know, you might say, oh, we'll just style the title attribute, but that's not always enough.
Because, what if I wanted something like this where I might have more complex information where I have, like, this bolded Google account and then my name and my email that are styled differently, like, we we I think this should be an opt in feature. There's currently a big discussion about it. So that's why I wanna talk about it.
And this is the current user agent style too. So a user would have to know that, this is what was currently resolved on. Currently, it was resolved on, if you have a touch device, a device that, doesn't have hover, then you'll show the button. So it won't be on desktop devices.
It'll only be on touch devices that you'll get this interest button by default as a user agent default. So that means that the user has to know that this is this precise media query that is a negation media query. If at media hover, hover none, then show it, else inline block for the display. And then also all these other styles.
And and this is my worry about shipping this as a default only on touch devices because people don't always test. You know? Sometimes, we you know, they don't always test on mobile devices, and then you get a little surprise, surprise. And then people are like, what's going on? Is this a bug? So this is what it looks like on Blue Sky right now if you use interest invokers on the app.
And, you know, there's there's been some discussion about this is better for accessibility and availability of this, but I think this is a worse accessibility experience. It's cluttering up the UI. So, anyway, if you have thoughts on this, while this was resolved yesterday, I added it to my talk to point you all to this beautiful issue here where it would be great to hear from the community and what you all think about how this should be implemented. Because I do think interest button is a good idea.
I think that we should have it, but I think it makes more sense in some cases than others. I don't think it makes sense as a default for everything. So I think it should be opt in. And, that's the the lovely issue number thirteen nine eighty. Can you believe there's been, like, over 14,000 issues in the working group? That's crazy. So go talk to people.
Anyway, that's our little France. Let's talk about UX patterns. So I'll go through these next two together. This is all about implementing natural interactions and providing guided navigation for your users. I I think that this is one of, like, the biggest things you could do to make your app feel, like, really premium and high quality and, like, app like.
So you can morph animations between states and provide stateful feedback. That's important. So your user knows that there was some feedback. Using view transitions between page views is also another way to make things feel really fluid. Intentional animation, the use of intentional animation to really guide your user's attention, and interactions that respond to user actions.
They feel like they have a say. They know what happened. They they get some response. I love this this little example from Tubic Studio because it's just so smooth. It just is such a beautiful website, and it feels like there is really a response to the user interacting with this screen. And you can see things moving between the pages within the pages. Like, I just think this is a really beautiful UI.
I wanna see more creativity like this on the web. And this is another example from Dribbble. One of the things I'm trying to be intentional about also is following designers who aren't necessarily developers and kind of getting their view on interaction design, like how they're thinking about user experience from high level. Because sometimes I think we get, like, really caught in the, you know, what's possible in, like, this sphere of web capabilities.
But, it's been interesting to kind of explore this space a little deeper. So just some general animations tips. You always wanna provide some visual feedback, but don't overdo it. Definitely be mindful of the type of feedback and the speed of the feedback for your users. You wanna animate from the source. So I showed some with the invoker.
Use natural easings. Like, we don't have real spring easings on the web, unfortunately, but you can approximate physics with the linear easing function. Also, just know that interaction is going to trigger user attention. So you can use that for good or for evil. Like, if I go over here and I wave, like, where are you looking? Probably at me, not on the the screen.
I don't know. Don't look at me. Also animating between states for better perceived performance so your user feels like there's something happening while they're waiting for a response. And then also thinking about natural motion and how people interact physically with their devices. So this is another really cute example. I love this designer, UE five forty, and I just wanted to recreate this little bubbly tool tip.
Like, I thought it was so clever that she had this little background that became the visual connector between the tooltip and the invoker. And so this is using just orchestrated animations. We have animations happening at different rates. You know, like the little bubble is kind of bouncing after the tooltip settles. But there's a lot of ways that you can create these sort of orchestrated animations, taking inspiration from design that's out there and just kind of recreating it to see how it's made and to kind of dig deep and explore that a little bit more.
There's also a couple of little big things that you can do that make UI feel a little bit more alive. This is just such a simple pattern where as you click on a button, it just scales down slightly so it feels like I'm pressing it. I wouldn't do anything more than 0.5 for the scale, but it's a really easy way to make a UI feel responsive, like responsive to you, to the user.
Another thing that you can do is add some blur as you're animating. So these don't have blur now. I'm gonna turn it on. And now I have a little bit of blur in the middle of this interaction, and it feels like it's coming from somewhere. It's doing something. One thing that is missing from the platform, I know that Adam has an open issue for this, is motion blur on the web. There's no current way to get this sense of movement from and to a place on the web.
You can only just, like, do a general Gaussian blur, which doesn't get you the full way there, but it does something. And I'm I like motion blur a lot, especially in this space of interaction design and quality on the web. So with linear, like, again, I I'm not gonna read this, but I am so into building mini tools right now to help me build demos. So I've I've been, like, taking this course, right, where I'm learning, like, React Motion and the way that, designers are talking about motion with, like, stiffness, damping, mass, velocity.
So wanted I to just, like, build a little mini tool for how to, like, convert that into the web language of CSS, and and we can do that. Like, we can we can use the tools to make the tools, to make the UIs. So this is just, a really complex animation timing function, but you can you can simplify this definitely with easing curves.
A couple of other, like, little eye candy things. Studio Co has some really beautiful designs as well. What I really like about how they design is they do a lot of this nice orchestration where you see staggered animations. You see these effects kind of come in really intentionally. You're guiding the user with what's moving in. Like, you're bringing that attention.
And I really like a lot of these stagger things, which you can do with sibling index in CSS. And, again, this could be a progressive enhancement where you're applying these, like, subtle animation delays to enable animations to trigger in an order that brings your attention to it. So for example, like here, I just have this animation delay where I'm using sibling index.
I'm multiplying it by point zero five seconds as the delay, and then I'm starting the entire animation two point two seconds later. That's what gives me, like, a little bit of a. You know, that's what it sounds like to me when I see this. Right? You too? No? Just me? You get this for free with scroll driven animation.
So so here is just a scroll driven animation where I have, like, a couple of little chips coming in. And this is just translating up from the bottom of the page where I'm doing an opacity and a translate as things are appearing in. So essentially, I'm just like doing a animation, appear, animation timeline is view, and the animation range is from the entry to 25%.
And so you kinda like get this for free because all those lines are coming in at their own rate, which is kind of nice. So SDA is awesome. Can't wait to have it cross browser. Another thing you should be aware of is, like, the direction of the scroll. Right? So in this case, this is a scroll triggered animations demo where as these cards are animating in, I want them to come in from the side of the screen that I am watching them, like, enter from.
So you can do that with, again, scroll state queries and scroll state scrolled, the best scroll states query, where first I'm going have them animate from the bottom. And I'm using just this amount to update it from 50 pixels to negative 50 pixels as the thing that is translating here in the key frame. And then I'm just gonna change that using scroll state scroll top to the negative value so it's reversing this.
Also, this little thing that says scrolling down and scrolling up, that's also a scroll state, scrolled media query or container query that's updating the content based on the scroll direction. So you could, like, do all this stuff with CSS. CSS is so cool. Right? Okay. Good. Another way to guide users are patterns like this.
So this is a table of contents that has a little scroll indicator to show you where you are in this wider, article, like in this page. And I think this is, again, a nice progressive enhancement that you can use to make, the user feel like they could understand and navigate this page a little bit better. Like, oh, look. See, I told you I added it to my site, that little top bar.
So you can do this by bringing your own scroll markers with scroll target group auto. And this is one of those things that I just think is such a nice, like, small addition that makes a difference. So in this example, I've got these sections, the intro, section one. These are all little anchor links within the page. And, there's gonna be IDs throughout the page that link to them.
Right? That's the setup. Then the parent of this little sidebar group is going to get scroll target group auto. So now these are all going to be little scroll markers themselves so you can apply target current to the scroll markers. And you might also notice I have this little pointer hand here. So as I'm scrolling, that pointer is updating, moving, shifting in addition to the style of that link itself.
And what we're doing here is I like to call this follow the leader or dynamic reinquering. So we're updating the position anchor is what we're doing here. So anchor positioning is technically in every browser, but it's technically also not baseline. That's a fun one. There's just enough browser inconsistencies and, like, some open bugs that it is not baseline yet, but it is in every modern browser.
So take with that what you will when you decide what to use. So dynamic re anchoring is this pattern where I'm going show this on hover now where you set this position anchor and explicit anchor on this little follower element. It's like a little magnifying glass that magnifies where the user is in this bar. And then when you hover over any possible anchor, so any of those possible icon buttons, it moves.
So the anchor name is going to update to hovered, and then you've got the position anchor of the follower that's going to follow it. So I'm also using a little bit of JavaScript here to do the default anchors. So if I, am not hovering on any of the potential anchors, it'll snap to that little possible anchor that I've saved in the state. But this is a nice little small cute thing.
So you can combine that with some of the other things like multi anchors. So I've got these tooltips. And those tooltips will also respect the positioning of the viewport. And you can do all of these, like, little hover things with anchoring and, like, all these nice little effects. And I'm getting these femoral tooltips and positioning things. And, I've got the position try fallback, so it does it all by default. And, you do need some JavaScript to preserve that state, but this is, like, all pretty much done in CSS, which is pretty cool. And morphing animations are another really cool thing that you can do now with view transitions.
And we heard all about view transitions from Brahmas yesterday. He's definitely the expert in the space. I always, like, ping him when I run into issues with view transitions, which is awesome. But, this is, like, something that we see all over the web, another way to make things feel nice and smooth. And particularly what I think is nice is that we now have scoped view transitions in Chrome one forty seven.
So as you learned yesterday, you can now start a view transition on an element and not on the document. So you don't have to block the entire page while an animation is running. And, you can have things running in subtrees and have multiple animations happening at the same time. So this is perfect for microinteractions and morphing animations.
This I think is a really great example of the utility of microinteractions and morphing within a UI. It's by Aditya Sur, and it's a, payments overview. Like, what did I spend this month? And when you click into one of those dates, it expands and morphs and gives you more information about what exactly you're looking at, what those icons are, how much you spent.
I think that this is a great example of how we can leverage these tools and techniques to really improve user experience and guide users. So, I like I said, I took this course by Emil Kowalski. And one of the demos here, this is all done in in React Motion in the course. But I was like, hey. I could do that with CSS and and a little bit JavaScript with view transitions. So it's, this feedback button that morphs into the feedback form. So to build this, we essentially wanna show one and not the other. We give them both the same view transition name.
We want them to morph into each other. And then, we capture these as separate layers so they animate. And you can just do this kind of stuff without having to install React Motion. You can build it with view transitions and guide your user, and this is like a fully functional form. Hello. I mean, that's not fun it's not it's not hooked up to anything. It's a demo.
Why do I say that? Another, like, little big thing is is feedback for users. So this is a copy to clipboard button example, also from that course. But it's a simple fade in and fade out interaction that you can create with view transitions. So it's just doing a little, And we have these two animations, the fade in and the fade out.
Right? And then we have this view transition old and new on the icon, and we're fading it out. We're fading it in. There's gonna be a little bit of a delay so that the fade animation can complete before the new one starts. Then we're easing it, and it's all it's just nice to do this with few transitions.
It's it's a beautiful, very complex, but very powerful UI. Another example that I like here is this this little interaction with a a retweet button. But what I like about this is that the numbers go up when they when they move back to, two eighty four, and it goes down when it moves up to two eighty five.
So this small subtle thing I think makes, again, a big difference, like that that effect. So to create this, we wanna store a direction variable in the root, and then we wanna update that based on the view transition. So here we have view transitions like sliding in and out, we also want to update the direction as we're doing the translation for the key frame slide out, slide in.
And we can update that value in JavaScript based on the toggle. And you can make these things that don't just morph from one to the other with a, crossfade, but, like, can actually move between each other, move between the values. So the last bit that I'll be quick about is adapting to the form factor. This is one where you really you know, we design on a desktop usually, and we build things on a desktop, and we test things usually in dev tools on a desktop.
And, I think that this gets us a lot of the way there, but there's still a piece of this where you don't really get that look and feel of when you're navigating the web. I think this definitely contributes to why the web feels a little bit jankier than apps is, I think, the way that we test things and build things.
But there's so many things that we can do with these modern capabilities to really, like, leverage touch based intuitive interactions. And, you know, there's also these things that we need to consider, like minimum touch target sizes, adapting the layout to the and the UI pattern to the form factor of your users. But one of these things is, like, with menus.
Right? So when you open a menu, often on desktop, have to find the close button. We don't like this. I don't even think this toggles. Like, it's a little icon. You have to find it. And it's not such a big deal when you're already used to using a mouse or even a keyboard to navigate. But on touch devices, like mobile devices, you usually can just swipe it away. Right? People are used to being able to toggle things open and close, like the different pages and sidebars and items here.
One of my colleagues, Philip, is here who absolutely despises that you can't do this by default on the web. So shout out to him wherever he is. I agree. I think this is a pattern that should be possible on the web, and it is. I mean, you can leverage, you know, scroll snapping and just scroll for this. So this is an example of, like, a very simple way to have free free swiping on the web, and that's by creating scrollers. We love scrollers.
Scrollers don't always have to be a bad thing. So in this case, this entire UI is a scroller. If you landed on the page, and didn't have this scroll into view style, it would look like this. And you'd have, like, a big scroll bar all the way across the bottom. But because I'm setting this up by immediately scrolling into this main section, I can have a scroller that has some overscroll, some area on the left side, and then you can just swipe it close. And it's using, you know, scroll behavior smooth and scroll snap type of x mandatory, and then hiding the scroll bar.
So it can be as simple as using scrollers to get free swipeability. But we're working on making this easier. So something that our team right now is working on is overscroll areas. And this is essentially built in gesture behavior in HTML and CSS. So right now, it is spec like this where, you have overscroll container as the attribute that you set on the overscroll area, and then you use command invokers to toggle the overscroll area.
So you hook it up with the ID. You set the command to toggle overscroll, and you set that up on a button. So this button has to exist right now. There's a lot of open discussion and questions. I think this is a really interesting API. If you wanna start getting involved in, like, providing your opinion on the web platform and standards, like, one has a couple of open questions. One is, do you need to have a button tied to it? Can we use, underlying ARGET actions?
Another is, how do we design this? Like, what about responsive design? So Brahmas, for example, just wrote a big issue about, hey. I think this should be in CSS, and this should be possible to change in CSS. And there's a lot of valid points and a lot of great discussion right now around overscrolling gestures and the future of this.
But the whole idea is that we want the web to feel more high quality and fluid and have all these capabilities built in instead of relying on, you know, third party tools or adding a bunch of scripting or figuring out what the right patterns are, I think that there's a lot that we can do to continue moving the platform forward. And it's come a long way.
It's been really, really cool to see how far the web ecosystem has come in the last few years, and there's there's even more we can do. So let me wrap up with these key UX principles. The first is to respect user preferences, which, again, we're all doing. Right? Yes. Good. I hear yes. Maximizing the content and reducing noise where we can.
I know you can't always do this thing with cookie banners. I do think you could minimize them a little bit, but there are patterns that we can do, like reducing the top and bottom bars and, like, making sure that we're focusing on most important content, implementing natural interactions that look and feel smooth and are inspired by physics, provide guided navigation for your user as they navigate through your application to help them understand where they're going and where they're coming from, and then adapting to the form factor of your user and their device. User experience is more important than ever, I think, in this current state of the web.
I think that having some design background and interest is going to be more valuable than it's ever been, and I'm excited to see this grow in our industry. And also the web is more capable than ever. Like I said, we've shipped a lot of great features in the platform, and now it's time to use them and make better user experiences with them. We can we can do better.
Raise your expectations for the web. I think that the web is the best medium to build on right now. Right? Yeah. It is. And I think that a lot of people in this room can set the trends and set the tone for what's possible on it. So think about the little big things that bring it all to life, make it feel more human, make it feel better, make it feel more high quality.
And thank you so much. I've got demos here. There's a link. You can follow me. Again, I promised you a blog post, so follow the RSS. Follow me on Blue Sky at Twitter. You can follow Chrome DevRel. New features are on developer.chrome.com, stuff that's stable. Not web.dev. And that's all I got for you. Thank you. I appreciate you.
That
was incredible. Thank you. Please join us. Me. Just me.
Okay. Should sit here? Here? Oh, okay.
That one, please. So I was just moving it. We've got time for a couple of questions. This one. That was a great talk.
Thank you. I'm so sweaty now. Sorry. Me too. It is hot up here.
Matthias asks, so many animations, maybe too many for users preferring reduced motion. Where would you draw the line between disabling animations completely and keeping some?
Oh, that's a great question. I mean, we would always say on the team, like, prefers reduced motion doesn't mean no motion. It means reduced motion. So think about how you're helping your users understand that there was an action. Like, that's so important. You might still wanna do, like, a little bit of an opacity change or a smaller animation versus just no animation.
And, again, being thoughtful with where and when the animation is. I didn't really talk about it much today, but there's also a lot that you can do with animation timing. So making things feel like smooth and snappy and fast where you're maybe in, like, a dashboard, but maybe if you're doing a more, you know, scrolling telling immersive experience, you can have slower animation.
So there's a lot of it depends. This is why I encourage you all to, like, break outside also of your bubble if you aren't in this design space, like, see what people are talking about when they're learning about and, like, discussing because I think it's really important to continue to try to expand our worlds more. Like, it's more important than ever to try to expand your world and not, like, be in a silo.
You know? It's it's tough out there. But anyway, there's a there's a lot of stuff with animation.
Yeah. It's not black and white. There there's a medium happy a gray area, happy medium that we can definitely spend some time finding. Alan asks, in your tool to to pardon? In your tooltip examples, you use flipbook but still have to set some top bottom stuff. Should be more automatically should more be automatically flipped?
It is usually flipped automatically. It depends on the UI. I forgot what the exact demo was. I think I might have updated position area. Maybe I didn't have to do that. I don't know. Find me after. I don't remember what the exact demo was. But, yes, it it does change some properties on all properties. So for the most part, it'll flip it automatically, but it doesn't use position area. It uses different positioning.
So it depends on how you're building it. But, yes, like, the default positioning will change. If you have anything that's fancier, like the animation or the, like, tooltip thing, you definitely have to update that. And I I think I have to just revisit because I also have, like, the demos in CodePens. So maybe I
Yeah. That's you're gonna be this you're this evening. Right?
Here. You're work fine.
Please do find Una Una if you want to have a look at that example in particular.
Yes.
Danny asks, will we see a interest dash source equivalent for normal popovers click?
There is one, popover open. So you can use popover open.
Someone who didn't add their names asks, in your examples, you have used a scroll state query to check for scroll bottom. Is there a start or an end keyword to keep the behavior when you when the scroll direction changes?
To keep the behavior. What do you mean by that?
I think because you I think that the users scroll state query to check for scroll bottom, I wonder I think they're wondering if what is the opposite of that.
Scroll top.
Oh, it'll be the top. Okay. So it's quite it's like, is that a start or end keyword to keep the behavior when the scroll direction changes? I think
what they might be asking is, like, can you set a style that applies on scroll bottom that stays for a while and doesn't change on scroll top? Yeah. Sure. You just don't override it on scroll top. In all my examples, I changed them, so they were opposites. But you could, like, apply a custom property or a style that like, if you set a custom property like the space toggle idea, like, turn something on and off, like, in theory, you should be able to do that.
It depends on how you set it up initially. So there's a lot of it depends for this question. I'm not even sure if I'm answering the real question.
But then again, please do come find you now. And and we can clarify that because I probably I'm also and possibly, I'm misreading it. This was we don't have time for more questions. Please give a big round of applause for you, and thank you.
People
- Adam Argyle
- Aditya Sur
- Bramus Van Damme
- Emil Kowalski
- Lea Verou
- Oscar Poweka
- Temani Afif
- z Hassan
Technologies & Tools
- anchor positioning
- border-shape
- contrast-color
- CSS custom functions
- CSS scroll markers
- CSS sibling-index
- interest invokers
- light-dark()
- linear easing function
- overscroll areas
- Popover API
- React Motion
- relative color syntax
- scoped view transitions
- scroll driven animations
- scroll snap
- scroll state queries
- scroll triggered animations
- style queries
- view transitions
Standards & Specs
- prefers-color-scheme
- prefers-reduced-motion
- WCAG
Concepts & Methods
- dynamic re-anchoring
- progressive enhancement
Organisations & Products
- Bluesky
- Chrome
- CSS Working Group
- GitHub
- Open UI
- WHATWG
Modern CSS capabilities open up new options for UI design — but more
options need better judgment. Una Kravets shares five UX principles for
deciding when a new pattern is worth using, all centred on building robust
experiences that genuinely serve users.















