 Hi, and welcome to What's New for the web platform. In the next 30 minutes, we're going to look at new and shiny features across privacy and security, powerful capabilities, UI design, performance and core vitals, and some new CSS and JavaScript platform primitives to supercharge your developer toolkit. Usually in these videos, we talk about features that are so new, so experimental, that may be only in Chrome, behind a flag, or just not ready for production. Ugh! We're still going to talk about those, but we're also going to focus on the features that recently gained full cross-browser support. These are the kinds of things that you could potentially use on the next site you build, especially if you're targeting modern browsers. First up, let's take a look at some new UI features. One big piece of feedback and frustration we hear from developers is, it's 2022. Why is it still so hard to style drop-downs and check boxes? You shouldn't have to rewrite the DOM to get a radio button to have a background color. Luckily, there are a few folks working on this and some pretty exciting recent landings. For example, the CSS accent color property just became stable across all modern web engines. This includes Chromium, which powers Chrome, Edge, Opera, and Samsung browser, WebKit, which powers Safari, and Gecko, which powers Firefox. This API allows you to change the theme color of previously hard-to-access form controls, such as native check boxes, radio buttons, range controls, and progress bars. In one line of CSS, accent color enables the browser to do the work of determining the foreground color against your set background and also works alongside the color scheme property to provide some nice automatic adjustments for light and dark themes. If you haven't heard about color scheme before, it's another CSS property you can set on the HTML root to give the browser some automatic control over text color, background color, and form elements to match the user's preferred UI theme. With this code snippet, the browser automatically creates a light and dark mode and uses the magenta accent color for form controls. Another piece of out-of-the-box functionality that recently landed across browsers is the HTML dialog element. This lets you create a dialog box, such as an alert or a prompt. When you add it to your page, it starts off hidden. But when you show it using something like the show model method, it looks like this. OK, that doesn't really sell it. Of course, you can style it however you want with CSS. You can even style the background overlay via the backdrop pseudo element. But the really useful part is it takes care of accessibility. It's announced as a dialog. It prevents keyboard focus from leaving the element. It also pops over the top of everything in a special top layer. So even if the dialog element is created deep in some nested component structure, it can fill the viewport. Even if the parent elements have overflow hidden or some other kind of clipping. And if you have a form in your dialog with the method dialog, submitting that form will automatically close the dialog and tell you which button was clicked via the return value of the dialog. I know I'm saying dialog a lot here, but it's a dialog. What else can I say? Oh, and common platform-specific ways of closing dialogs, such as pressing the escape key, well, they just work. But whatever I have a pop-up that isn't a dialog. The Open UI community group is actively working on how to resolve more complex and expanded form controls. Folks from all around the web have come together to identify the shared parts of these UI components and have proposed experimental solutions like the select menu component and pop-up attribute. We're working to explore shared behaviors like light dismiss and enable more broad styling of a variety of form controls, including dropdown menus and tooltips. Here we have some demos of the select menu component from Microsoft which would enable a whole slew of new UI styling experiences. Open UI is also thinking about solving other component experiences like tabs and anchor positioning. You can play around with the select menu now behind a flag and chromium, join the conversation and provide feedback to Open UI through the GitHub page. Back in the world of recently cross-browser features is datetime local. It's an input type, so you use it like this. And it gives you an input where the user can select both the date and the time. This is how it looks on desktop Chrome and Chrome on Android. You can also set validation constraints like min and max dates, and that is reflected in the UI. That's it, that's the feature. There's also a new font format coming to browsers. Color V1 is an evolution of the Color V0 font format which adds gradients, compositing and blending, and improved internal shape reuse for more crisp and compact font files that compress more efficiently. This compression leads to some nice performance gains as you can see here when compared to the bitmap alternative of that font file. Color V1 fonts tend to be much more crisp and they scale better as well. This new format makes it easier to stylistically work with color fonts and icons like Emoji to create expressive headings and performance interfaces. For example, instead of using images for icons, they can be rendered as color fonts. There are some new experimental properties like font palette and override colors that give users a new entry point for styling web fonts with Color V1 as well. Here's an example of where you can use override colors to restyle the bungee typeface. It's pretty cool to see it in action. Let's step away from pure UI features for a moment to talk about performance because it doesn't matter how good the UI is, if it's slow and sluggish, it's still a bad user experience. One improvement here is the back forward page cache or BF cache for short. Now, this is a feature that was late to Chromium. It's been in Firefox and Safari for a number of years, a big number. But it's in Chromium now too. Here's how it works. You're on a web page. You follow a link to a different page, but the previous page is kept around for a bit, frozen in the background, meaning if you press back, it happens instantly. This doesn't happen for all pages, only pages where it's unlikely to cause problems. Thankfully, DevTools is on hand to tell you if it works for a given page, and if not, why not? Speaking of web pages, I don't know, I need to transition. Images are one part of your page load that starts loading early. As soon as the browser sees them in the source, it cues up that download. This happens even if the image is hidden, and even if it's all the way down at the bottom of a really long page. But now, one simple attribute means the browser will take the image's visibility and position into account when it comes to starting that download. And it works on iframes too. If you put loading equals lazy on the big important images at the top of your page, they will load slower, so be careful. But adding it to less important and off-screen images means they don't fight for bandwidth, and more important things like style, scripts, and high priority images take precedence. We have mentioned the benefits of lazy loading before on the stage, but now it's available across browsers, arriving in Safari 15.4, and we've continued working with our CMS partners, so it's now available in WordPress, Wix, SilverStripe, Drupal, and others. Sticking with images for a moment, if you give images width and height attributes and set their height to auto, they'll maintain their aspect ratio even before they load, which avoids layout shifts. Now, I know what you're thinking. Jake, this happened back in the blissful carefree days of 2019. Why are you talking about it now? Yeah, that's fair enough. But what I really want to talk about is this, the aspect ratio CSS property, which lets you achieve the same thing for all elements, not just images. A little sprinkle of this on your iframe, your component div, your grid layout, and the element gets a fixed aspect ratio. So if the width is 1,000 pixels, the height will be like 500. It's going to be 562.5 pixels. I imagine there's a lot of you out there that just knew that off the top of your heads. But this is particularly useful for embedded content, placeholders, or images that aren't literal HTML images like CSS backgrounds. Using this, we can finally say goodbye to the padding top hack. Another CSS feature with some performance benefits is containment. The CSS Contain property lets developers tell the browser how to render the content on the screen and isolate a DOM subtree. This, in turn, enables the browser to defer rendering of size, paints, and layout for speed and efficiency. We don't have a lot of time to get into the intricacies of this one, but check out my article on content visibility, a nice performance enhancement you can do with containment to learn more. We'll link it in the description. Containment is also a prerequisite for container queries, which we'll talk about a little later in this talk. But before we get to that, let's talk network priorities. Browsers try to be as smart as possible when it comes to fetching stuff. Things which block rendering get an ultra high priority. Then, when the browser knows where things are, it gives higher priority to things in the viewport. But there are cases where the browser doesn't have enough information to make the right decision, like two async loading scripts, but ones way more important, or two iframes, or two visible images, where one is more important, or two preloads, you get the picture. But now you can get the picture faster using priority hints, which is very recently stable in Chrome. So recently, in fact, it isn't stable when I'm recording these, so fingers crossed. How does it work? Well, same example as before. And bam, the fetch priority attribute lets you hint whether a fetch should be high or low priority. This can have a significant real world improvement in terms of largest contentful paint. It isn't something you'd use all the time, but in cases where the browser's default priority isn't optimal and it's harming your core web vitals, this lets you make little tweaks, hit those numbers, and improve user experience. Although it's only available in Chromium right now, it's a nice little enhancement that works today and will benefit other browsers in the future. Another nice enhancement is size adjust. This is an experimental CSS property for web typography that improves performance by reducing cumulative layout shift. And how does it do that, you ask? Well, fonts come in all shapes and sizes, and even fonts of the same size may appear completely different. One 16-point font might look a lot bigger than another, and that's where size adjust can come in. With size adjust, a user can make visual adjustments to a font's size, including local fonts to make them look closer in shape to the web font intended to replace it. Since a web font will replace the local font after it's downloaded, this reduces the overall cumulative layout shift of the page. To get an optimal size adjust value and help prepare for a font swap on your page, Malte Ubol created this great size adjust calculator that you can see here. We'll link to it in the description below so you can try it out yourself as a progressive enhancement. From high-level design features, let's snap right back down to low-level primitives. In the past year, SIMD landed in stable versions of Chromium and Firefox. SIMD stands for Single Instruction, Multiple Data, and is a type of parallel processing in Flinstaxonomy that can be accessed via a variety of CPU instructions. Look, I don't really know how it works. What I do know is it's a low-level way to run particular small operations in parallel, and it's a common optimization in C++ implementations of image, video, and audio processors. Until now, those optimizations were lost when compiling those programs to WebAssembly, but now they're attained. It isn't supported in Safari yet, but you can pretty easily compile the WebAssembly twice, creating a package that uses SIMD and another that doesn't. That way, Chromium Firefox will get the benefit of faster WebAssembly, but things will still work in Safari. That's what we did on Squoosh to speed up image compression. Before we close out this section, we want to call out a new performance metric that we've been experimenting with. We're calling it Interaction to Next Paint, and it considers not just the first interaction, but all interactions on a page. For example, it'll measure the time between your user pressing a play button and seeing the pause button replace it. To be more specific, it records the time from when a user interacts until the next frame is painted after all event handlers run. The metric also does a better job of capturing the interaction latency as experienced by your user, highlighting any unexpected slowness in how the UI responds. Check it out and let us know what you think. Okay, let's move on to privacy and security. One of our long-term projects is to improve user privacy by phasing out third-party cookies and cross-site tracking. Other browsers have done this, and it's created some compatibility issues, so we've been working on APIs that will help us keep existing user-friendly functionality. Let's say you have something like a chat app embedded in your site that manages its own login state. This would traditionally work by allowing the embedded site to have its own single set of cookies regardless of where the site is embedded. This is the third-party cookie behavior that's going away. Great for privacy, but it breaks legitimate, useful, friendly cases like this embedded chat. If the chat doesn't have its own cookies, it can't remember you're logged in and you'll get logged out every time. If you're chatting with your bank who uses a third-party chat app and need to get help across platforms or sites, this can be a big problem. So what can we do about that? What if there was a way to preserve the helpful part of cookies but remove the cross-site tracking part? To do that, we're experimenting with cookies having independent partition state or chips. You know, like cookies, chips, chocolate chips. Doesn't matter. This is an attribute passed when setting a cookie, meaning this cookie won't be blocked, but it won't be shared either. If the cookie is set when the chat app is embedded in A, then it'll only be available when the site is embedded in A. When the chat app is embedded in a different site, it'll have a completely different cookie jar so it can't be used to track you across sites. However, you can still preserve the session. If you rely on cross-site cookies and want to make sure things will keep working smoothly, check out the chips origin trial, which is available now. Okay, I think it's fair to say no one goes to websites for the advertising unless you're really into that sort of thing. But effective ads keep a lot of services cheap or even free. Ad platforms currently use tracking techniques to deliver relevant advertising, but the door's closing on those patterns. So we're looking into ways to allow platforms to deliver meaningful ads without the negative impact on privacy. Our first swing at that was called Flock, but the feedback was pretty strong, to say the least, particularly that it didn't protect privacy enough. So taking that feedback on board, the next experiment is the Topics API. It gives the page a few topics the browser believes the user is interested in, which can be used to figure out the best ad to show. Only high-level topics are shared externally, not the user's browsing history, and different sites get different topics for the same user, making them not particularly useful as a cross-site identifier. See the description for links to content that goes into more detail here, particularly how the anti-fingerprinting measures work. This is an origin trial right now, and again, we're really interested in feedback. Speaking of fingerprinting, we're joining other browsers in taking steps to reduce the amount of data that is automatically shared in the user agent string. It's really important to build user-customized experiences, but it's usually a bad idea to use the user agent string to make styling decisions or to conditionally serve different content. That being said, sometimes it's necessary for things like polyfills or working around particularly nasty bugs. Instead of using the user agent string, check out the User Agent Client Hints API, which is supported in Chromium-based browsers right now. Details are linked in the description. And on the topic of user safety, there's more. Did you know that passwords aren't the safest way to manage user accounts? Although we aren't quite in a world without passwords, there are emerging ways to provide better support for password managers so the user experience is seamless and more secure. In terms of new stuff, we're working on pass keys in Web Authent, developed as part of the Fido Alliance. This will allow registered credentials to be synchronized across Android devices so you don't always need to enter a password. And to sign in across devices, you can use your phone as a security key by scanning a QR code. Speaking of powerful capabilities, we really want the Web to have app-like functionality so you can create rich cross-platform experiences. For example, most operating systems on both desktop and mobile have some sort of media integration where they tell you what's playing and offer you controls to pause, skip, and seek. In some cases, those controls appear on a different device. The song's playing from your phone, but your watch displays the media controls. The media session API lets you do all of that via the web, displaying and reacting to media controls across Windows, Mac OS, Android, and iOS, including related devices like smartwatches. Browser support is great as of this year with only a tiny bit missing on Firefox for Android where the API exists but it doesn't trigger the operating system UI. So we're close to full browser support but there's no reason to avoid this API given that it's a really nice enhancement. Okay, here's another operating system integration feature but this one's much newer. The Window Controls overlay is a Chromium only feature right now but it's a nice bit of progressive enhancement for installed apps. When you install a web app on desktop, it opens in the window kind of like this but a new feature that landed in Chrome 99 can make it more like this. Okay, I know that looks broken. You wouldn't leave it like that but this allows you to put web content in that area in the middle, like this. It isn't something you'd want to do with every web app but it's something a lot of native apps use to good effect. I mean, it's certainly something browsers do by putting tabs in that area. You can activate this feature with an option in the web app manifest. Then you get CSS environment variables and an API to tell you where all the window controls are so you can place elements around them. To control navigation, browsers have APIs like history.pushState and popState events for handling session history but if you've ever used them in anger, well, you probably got angry because they're not very good. So we're having a bit of a do-over and calling it the navigation API. This gives you the current windows view of same origin session history unless you intercept navigations meaning you don't need to rely on click events on the links. This will make it way easier to manage state between reloads and traversals of web apps. It's in an origin trial in Chrome right now headed for stable pretty soon. There's more to it than I've been able to cover in a few seconds so check out the description for links. Another feature we've been looking at in the world of navigations is one that developers including me have been requesting for ages but it's trickier than it sounds so it's alluded us for years. It's the page transition API, an API to simplify creating rich animated transitions between pages and page states using familiar concepts like CSS animations. It allows you to turn this kind of experience where states just switch from one to the other into this where you get smooth, custom transitions between states. I've got a whole other talk that dives into the details of this so check that out but not yet. We've got more to talk about here. And one last web app improvement we're currently trialing is in addition to web app manifest that let you provide different colors for light and dark themes. This is similar to color scheme styling with prefers color scheme for websites except it's for PWA interfaces. It's a seemingly small addition but it makes a really big impact to user experience. This is currently in an origin trial in Chromium. Another input type that's been historically difficult to access is the eyedropper for selecting color values. Well, it's a lot easier now thanks to the conveniently named eyedropper API. This is in Chromium but only on desktop as it's a fairly specific desktop interaction. With a quick API call you can activate the eyedropper following a user interaction and then the user can click somewhere and the capture color is sent back to your web app. It can even capture colors outside the browser making it a fully app-like experience. Speaking of input, let's talk about virtual keyboards. Devices like tablets or mobile phones typically have a virtual keyboard for typing text inputs. Unlike the physical keyboard that's always present on your desk a virtual keyboard appears and disappears depending on the user's actions and needs. With the virtual keyboard API users can programmatically access a virtual keyboard from JavaScript pass information about the keyboard into CSS through environment variables and style it and provide a policy to determine if the virtual keyboard should be shown. Thanks to Microsoft you can explore this in Chromium but it isn't quite ready for widespread use yet. Okay, if you've been enjoying the visual demos in this talk so far sorry, there's none of that for a bit because we're gonna talk about scripting primitives. Loads of new stuff landed over the past year. First up, have you ever done this? It deeply clones an object but come on, it feels like cheating converting it all to a string then back again? Well now, we have structured cloning. Look at that browser support chart no one had this last year now it's across all browsers. Just give it a whiz and a clone there is. Not only is it cleaner it can clone more things like blobs, image bitmaps, type to raise it can even clone object structures that have circular references. This isn't a JavaScript feature it comes from the HTML spec but it's also implemented in Node.js and Dino. Sticking with scripting features that come from the HTML spec here's how you convert an image blob into something that you can display in a canvas. It's kind of ugly and creating and revoking object URLs is an easy place to memory leak but now that the create image bitmap API is supported across all browsers that page of code becomes this. That's it, done. Not only that but you also get way more control over how the image is loaded. It's really useful for loading textures for 2D canvases and WebGL. This API is also available in a worker which is particularly useful for off-screen canvas although that part isn't quite cross browser yet. Okay, let's talk about some core JavaScript because a whole bunch of stuff has become cross browser compatible. They are top level await. You can now use await at the top level in JavaScript modules just like that. Classes can now have private properties and private methods. They're denoted using that symbol. You know, the one that everyone has a different name for. The cross hatch, the pound sign, the sharp, the square, the hash, the hash tag, the octophor, the tic-tac-toe. Unicode calls it the number sign. Doesn't even make sense. Whatever you call it, if your property or method starts with it, then only the code internal to the class can access it. And have you ever done this to get the last item of an array or maybe this? Well, now there's the app method which gets an item from the array by its index and accepts negative indices to count back from the end. That method is also on strings and typed arrays. All these are now cross browser. And shared array buffer is also cross browser. Shared array buffer allows memory to be shared across pages and workers. That memory sharing is pretty essential for multiple threads with WebAssembly since it allows code to be ported from things like C++ and Rust with minimal performance loss. Its browser support story is a bit wild. In 2018, some really bad CPU bugs were discovered, meaning browsers had to pull this feature for security reasons. But since then, browsers have been working together on a feature called cross origin isolation, which dramatically reduces the impact of these CPU bugs. So now the feature is back safely across all engines and platforms. But what about the bleeding edge? If you've used the routing library before, you've probably seen patterns like this. Well, now the web platform understands them via the URL pattern object, allowing you to validate URLs according to patterns and extract the parts. This shipped in Chromium browsers late last year. It isn't in other browsers yet, but there's a polyfill allowing you to use it cross browser today. But the benefit of this being part of the platform is we can start to allow other web platform features to make use of these patterns, such as CSP and service workers. Okay, we really don't have time to do this one, Justice, but let's talk about the WebCodex API. This is actually a whole suite of APIs that give you low level control of image and video decoding and image encoding. From pulling the frames out of an animated GIF to encoding a WebGL-generated scene to an H.264 video all within the browser. Browsers have had image and video codex built in for years, but this API gives you low level control of them. It's something that Chromium is leading with, but we're looking forward to more cross engine support in the future. Okay, we're on to our last section. We've already covered a bunch of CSS stuff, but let's take a look at some CSS features that aren't really styles. They're fundamentals that make writing and structuring CSS easier. First up, cascade layers. Look at that. This feature wasn't there at all last year, and now it's everywhere. That wasn't an accident. Engineers and standards folks across browsers work together to launch this feature around the same time. Anyway, that's enough patting ourselves on the back. What are these cascade layers? Well, a site's CSS often ends up being a combination of resets, utility classes, components, libraries, and sometimes you can find yourself adding to selectors just to beat the specificity of another rule. Cascade layers solve this. You can put imported styles into a layer and also group styles using these layer blocks. Now by default, a layer that appears after another can override all the styles from the layer before regardless of the selected specificities. Although you can also define the order of layers up front. So here we have reset styles, then utils, then components. That's the order they apply. No more fighting over specificity. Styles in a layer have lower specificity than those outside a layer, except if the styles are marked important. When you do this, those styles apply in reverse layer order. Sounds weird, but this is how CSS has behaved all along. User agent styles are like a layer. They have less specificity than other styles. However, important user agent styles have a higher specificity than almost everything. That's cascade layers. Please take a guess in the comments at how many times we had to record this for me to pronounce specificity correctly every time. It was once, pew, one take Jake. One of the new CSS features I'm most excited about has to be has, pun intended. The has pseudo class is a powerhouse for CSS selection that lets you check a parent for any attributes in its scope. This has been called the parent selector because it checks a parent for specific children and lets you style either the parent or any of its children based on this information. For example, figure colon has fig caption looks for a figure with a fig caption inside of it. Then you can style the figure itself. In this code block, we're saying if this figure contains a fig caption then style the image within the figure to have a margin bottom, making some space between that image and the fig caption. Super handy. You can combine this with other selectors that are a part of the same spec like knots and do some really specific styling based on the availability and state of a parent's children. Here we're styling a form with a submit button that is not disabled. We're giving the form a border color shift to green as an additional visual cue that you can hit submit since that button is no longer disabled and you're ready to move on. Has recently landed in Safari and is currently behind a flag in Canary if you want to give it a whirl. Now, traditionally, we've created responsive designs using media queries where you've changed which styles apply based on the width of the browser window. But a wider browser window doesn't always mean a wider component. Catering for this with media queries is hard. The components start small, gets bigger, then gets small again, then gets bigger. And if the same component is used in other places with different layouts, good luck. Container queries solve this by letting you apply styles based on the width, height, style, or state of any parent container allowing you to create truly component-based responsive interfaces. This is a huge change from the current global approach we need to use today which lacks the finer tools necessary to apply nuanced changes. With container queries, each component owns its responsive information and responds accordingly no matter where it lives in the UI. In this example, we see the same component in a grid with three different parent sizes where using a container query to style the card and you can see how it looks different depending on how much space it has available. Similar to media queries, app container can accept a size value or a set of values. But unlike media queries, container queries require containment to be set in the parent and can currently query two-dimensionally with built-in logical properties. We used both dimensions in the Design Sember landing page to showcase this power. Another cool thing about container queries are named containers. If you have a child nested within one parent but it needs to query another, you can create container rules that target this exact case. In this demo, the button within this product card has its own nested responsive styles and lives within a responsive card. At times, we want the button itself to reposition based on its parent, so we use a named query to allow for multi-dimensional stacked responsive design. This is currently supported in Chrome behind a flag and in Safari's technical preview. Hopefully it'll be green across the board next year. But in the meantime, we have a polyfill you can use to make it work across browsers today. Check out the description for links to that and more information on everything we've talked about in this session. The web has come a long way for one year. We're excited about what you can do in browsers today and for the possibilities for tomorrow. We've been meeting and working across browser vendors to make sure your web development experience is even better through an initiative called Interop 2022. Along with Apple, Buku, Igalia, Microsoft and Mozilla, we aim to launch some of the top requested developer features and resolve some of the most infuriating compatibility bugs. For 2022, we aim to focus on these 15 key areas to ensure that behavior is fully interoperable between browsers. Then in 2023, we'll work on another set, influenced by feedback from you. Ultimately, we want you to be able to build great experiences on the web and interoperability or browser support shouldn't be the blocker. There is so much innovation to come and it's a really exciting time to be a web developer. Thanks for watching. Bye. Ugh! It's not even plugged in. Don't know how this is happening.