 We have taken, so far, putting maths in my head, I really struggled. Well, thank you. Do you know what, the power of editing, no one will ever know. We have taken eight fifty... We have taken minus four. This is it then. Oh, it's happening. The final episode of our Christmas special, finding the best feature. We haven't really agreed. No, we haven't agreed last year. We're not agreeing this year on what to call this, really. So far, we have taken 12 features. That's correct. And we have whittled them down to, well, two so far. Yes. And that is sharing on the web. Yeah. And background fetch. Yeah. So background fetch will have to endure another match before it gets to face sharing, or maybe not. Who knows? We will see. We have four features left. We've been picking these at random, which is why we're so scrappy at remembering them. But yeah, it's time to do the last four. Yeah, you start picking. Oh, it's me. Because of symmetry. Yes, excellent. So I'm going to pick this one. And I have prefers styles. Prefer styles. Oh no, it's not Paul Lewis. It's Jake. Did you put the wrong face on? Yeah, it shows that we had the software ready, just in case he walks in and wants to do a feature. You never know with him. Sometimes he just appears and just takes over the show. He just can't let go. Oh yeah, you want me to talk about this, right? Okay. You don't have to. But again, this is a little bit of a two for one. So I know, I know. This is a CSS feature. It allows you to hook into things that the user prefers, like a preference that they have expressed usually at the operating system level. That's a good description. Don't laugh at me. That's what it is. They've said, I prefer everything to be dark. I'm sad about life. So can you do that? And yes, we can. Yes, we can. And now you can do it on the web as well. So this is how you'd have it. You'd have your media query, your first color scheme dark or lights, and you provide your exceptions to your styles. Sometimes it would be really, well, we did this with the Chrome Dev Summit website, where we were just overriding a series of custom properties. Great. We did that plus, I think, two or three minor adjustments for contrast on some elements. But other than that, that pattern worked great for us. It worked really, really well. You can also access it with JavaScript using match media, as you can with all the media queries. The other part of it is prefers reduced motion, which again, is a feature that operating systems are exposing. Does it bug you that they didn't just make it a true, false media query? That is a good point, but I think I know why. So something that Adam Argyle, our colleague who does a lot of the CSS stuff, explained to me is the intent of this is not to cancel all animation. So you might, it's more to, if you had like a constant animation going. True. Like it's sort of like a wavy thing on the page. But it's a reduced motion. Like what is different between prefers reduced motion reduce to prefers reduced motion? Oh, that's true, isn't it? I find it oddly hard to memorize this, like to actually remember what the correct. That, yeah. Because the other one is prefers color scheme, light or dark. That makes sense. Yes. Because it's an open-ended question, but prefers reduced motion is a yes-no question and we reply with reduced. It should be prefers motion. Yeah. And then you can add in non as a third value to like say just no, no. Oh, roller coaster. Or yeah, oh, just go, go nuts. Yeah, just go for it. Just like make everything move. Make the whole page spin round. Just do in CSS, star, animate, rotate and see you've just gone. I want to do that. I want to see what that looks like. Who wouldn't want that? Because maybe you're stuck in a washing machine and your laptop's outside. Can you counteract the rotation? Exactly. So why wouldn't you want to do that? You've really spoiled this feature for me by pointing this out. Takes too disangent. It's wrong. It's the wrong shape. Oh, like, I mean, it doesn't matter now. You don't want to win anymore. No, I hate this. This is disgusting. I mean, okay, let's try and ignore the naming. This is an important feature for people who like maybe get nauseous with like certain kinds of animation and they've told their operating system that your website can now react to it using this slightly badly named API. So there you go. Slightly. Fine, that is the feature. All right. Yeah. Up against, up against, for first reduced motion is native, lazy loading. Native, lazy loading. Check that out. Okay. Yeah. All right. Let me tell you what is it? It is. Why is it? Big fan of this feature. Basically, it allows you to just put a new attribute on images and the browser will automatically not load them until you scroll them into view. Right. Yes. Okay. And she's a fun fact. It also works on iframes. It does also work on iframes. Does it, Jake? Right. Okay. Story time. We talked about this on stage at Chrome Dev Summit. I did, in fact. And I, and someone said it works on iframes and I ran on stage to tell you you were wrong. But it was I who was wrong because I was thinking of the aspect ratio hack that we talked about in earlier episodes. Which does not work on iframes. Does not work on iframes. This one. So yeah, both iframes, you are forgiven. Thank you. Thank you. Although I will not let you forget it. Thank you. Yeah. So both images and iframes you can now just put on your page and don't have to worry about the initial payload because the browser can load them lazily. Right. And we know that there's like you can do something with intersection observer or scroll events. Like it is, it is a good amount of code, but it's mostly just a super convenient feature. Yes. It's polyfillable. It is. Absolutely. That's why the people have written this with intersection observer or. It's only, I wrote it for the Chrome Dev Summit website and it's like four lines in intersection observer. But it does depend on JavaScript. How do you progress of enhancement? How do you make sure the image loads if JavaScript is disabled or broken? Yes. But still not loaded if you have JavaScript. And that's actually quite challenging. It is really challenging. So what do we think? This is actually interesting. Both are fairly high level, fairly simple. I think native lazy loading does much more good for the web health overall. So here's my summary of the two or the pros and cons. For first styles, there's no polyfill other than giving user a button to press. Which most of them you want to do anyway because just because the user has dark mode enabled, maybe they don't actually want dark mode on the site right now. Possible. Yeah, I think that is especially true. Like if you're in a darker room than usual, I don't. You don't want to switch your operating system to dark mode just because you're in a darker room. Yes. Especially if you're just reading one website that's a bit bright and it has an option. Okay, I'll take that. That's fair. Whereas with native lazy loading, it is extremely volatile. That's true. It's so easy. But that might still be a bar that stops developers doing it. And especially with the concerns around JavaScript where it does get orders of magnitude more complicated. Yeah. And native lazy loading can save people a lot of data and just having an attribute that does it. And it's resilient to Java. Like it doesn't use JavaScript. Like people who surf with our JavaScript or who have disabled or when it crashes. Yes. It will stay functional. This is actually... Native lazy loading is a really good example of the extensible web manifesto in progress. Yes. Because we did all the low-level stuff, which is intersection observer. Actually, it's just that. And it's just intersection observer. But then we have gone and done the higher-level thing. Here, we've seen how people use it. Does the spec actually rely on the... Does the native lazy loading spec rely on the intersection observer spec? That's a good question. I actually, before we came to film this, there's discussion ongoing around the spec for this. And part of the thing that is happening right now is the discussion of how the intersection is calculated. And I don't know if it is referring directly to... What might actually is more likely to happen? I think it would be less... If this HTML feature depends on intersection observer, what they're probably more likely to do is take those intersection things into the HTML spec and make the intersection observer spec reference the HTML. That would make sense. And it would probably be desirable. Web standards. There you go. It's native lazy loading, isn't it? Yeah, that's what I would put my money. And Dark Mode is very trendy. But as you say, you can do it with a button. Native lazy loading is... Yeah, lovely solution to that problem. Wow. That means native lazy loading. Native lazy loading advances. And now we have to find out who native lazy loading faces off against. Right. So that one made my decision. Form elements. There's a more specific thing there because we've had form elements for... We did have form elements on the platform for a couple of a while. For a good one? Yeah, that was good. Thank you. And I will tell you, again, a couple of features sort of rolled into one. Did I have one double? I had one double feature. And it's in the finals. Well, okay. So that's the form element. Found it. There it is. What do you think? When you do this here, this label... Well, there are a few behaviors that are attached to this input here. If you click name because it's part of the label, it will now focus the input. Yeah. Also, it doesn't have to be inside the label. It can have reference for an ID. Yeah, for an ID. But also, when you hit submit here, the value foo or whatever the user has typed in there will be sent to the server post with this action. Yes. This thing here, this fancy thing, fancy custom input, does not have those features. Not because it's custom. So it does now. Oh. Yeah. So there's a couple of ways you can do parts of this. In terms of the submission thing, this is an event you can hook into. So the add event list is form data. What you get is an event object. It has a form data property. And that will contain what the browser has collected about the form so far. And you can modify it. Oh, so you can also inspect the other data. You can append your own, but you can also mangle whatever is already there. Exactly. Okay. So it's like a post-processing step, which includes adding stuff. So that could be a simple way to have your custom elements, whatever, take part in the form properly. Yeah. Or you could do this. Custom elements. This is a custom element feature. Now, the key here is to say form associated equals true. That's magic, isn't it? That is magic in the same way that the observed attributes. Right. One is magic. And so with this being true, it's saying, you know, the browser now knows this takes part in the form. And then you can do this attach internals thing, which is like a way of getting a secret API. So secret. So secret. Which you, and it's a little bit how when you attach a shadow root. Right. It's sort of a little bit like that. But it's not an element. What it does, it just has a load of like APIs as part of it. So you can see these things here. So getting the form will return this internal form. That's bomb. Yeah. Yeah. And element, if you've got an input element or something, dot form will always return the form. So you're just kind of good practice to do that. Yeah. To do that. To do that. But we've got some method. And what that will do is set the value to yes, please. And that's telling the browser, this element, which is taking part in the form, now has this value. So you will be internally listening to clicks and stuff and the shadow root and whatever. And updating what the form value is. And you can tell it if it's all valid or not. All practices apply on how to do input or whatever, custom elements. But now we can just participate in the form part. And by setting the validity when the user hits submit, if one or more of the elements are not valid, it won't submit and it'll do that thing where it shows the little pointer and say, this is the wrong one. Do something about this. And that is the feature. So I have one left. One left. Do you know which one it is? No, I can't. I can't remember either. I can't remember what it is. It must be a good one. From entries. From entries. I'm going to try it with a jake. Go on then. That was really good actually. Close. That was much better than my stupid attempt. Go on then. Talk us through from entries. From entries is, I actually really like it. So there is object.entries, which will turn an object into an array of key value pairs. Yes. So now you have a basic list representation of what this object is. This is old. But this is so useful, though, for iteration. You can iterate over the, you can just write for loops to get key value and get both at the same time. You can actually map over the entire object and say, oh, I want the keys to be uppercase, or I want the values to be plus one, or both at the same time. However, once you do that, how do you then reassemble this list representation back to an object? And that is pretty much what from entries is. It's the inverse of object.entries. It takes a list representation of key value pairs and just gives you the object. And I think, well, exactly what you said there, that's the cases where I've really needed this or wanted this. And it's when I've done, you know, I want to map an object. Yeah. Mapping a array is really easy, but I want to take this object, I want to map over the keys and the values and output something different. And this just lets you do it. Yeah, that's it, that's it, that's it. All right, all right. Let's have a think about this then. Um, right. So we've got from- From entries. From in form. Is, from entries is a polyfill which you can write with reduce as a one liner. Oh, that's a good point. But, but, yeah. It's not a new capability. It's super nice that we have it. It makes it much more like code. It's just much more expressive. But you can just define your own from entries and it's a one liner with reduce. It's, oh, views reduce. Yeah. Yeah. I'm not sure if there's performance implications of mutating the object over and over, but in the end. No, it should be fine. So yeah, I would say form. Yeah, because you clone the object and then just mutate it. Yeah, I think based on that, it's not a new capability. It's nicer. It's there. It's good that it's there. But the form element is a new capability. And you could say part of that is just like a custom element feature. A lot of people are like, well, I'm not bothered about custom elements. I was thinking, even if you're using React, being able to define your own custom form elements, this makes it much more attractive to use custom elements for it. Because you get, I think so as well. It just ties it into how the browser already behaves. Yeah, agreed. All right. So form elements advances. Yes, it does. It goes against native lazy loading. And this is, I would say this is tough. Because we're like, I'm like, this is something. The native lazy loading, something I encounter on every site I build. And I'm often too lazy to do it right. I will omit progressive enhancement or just do the intersection observer thing and don't basically ignore people who don't run JavaScript or where JavaScript breaks. Form elements is not polyfillable, but I don't encounter it often. I will always say, I don't know how much I care about people who disable JavaScript, because as much as I, how do I feel about people who disable SSL in their browser? You know, it's kind of like, well, why do that? You know, it's part of the web. Part of the platform, yeah. But the thing I do care much more about is the people who haven't deliberately disabled JavaScript, but the people who are maybe running a browser that is older than expected and maybe didn't test properly so the JavaScript is failing. Yeah, JavaScript file just doesn't run because you have one const in there and the browser doesn't do const. Yeah, or a server hiccup that suddenly just returns an empty file or a 404, and this does happen. Wrong time. Yeah, the MIME type goes wrong. Something like that. And that is one of the reasons that I'm super keen on progressive enhancement. You know what it's had been. It's never been about non-Jobscript people for me. It's been about performance and resilience. So I do like it for that and I like that it lowers the bar to save the data. Doing the right thing. Yeah, absolutely. The form elements thing is a new capability and it has that... It's not entirely progressive enhancement because it still depends on JavaScript. Yeah. But it depends on less JavaScript to do the same thing that forms should do and it will get you some of the accessibility for free because if you're using the native validation stuff and the native value stuff, I'm assuming, I mean, the data is there, that can be exposed to accessibility APIs. Yeah. Now, I want to say like you can... There is form data as an API to assemble form data and turn it into a multi-part MIME body or whatever you need. Yes. But there is no API to do a post navigation. Oh, that's true. I mean, you can... So there's actually no... Because I thought like, oh, you could just use a form. You can cancel the submit and then assemble your own form data. But there is no way to send that form data as... Oh, that's interesting. As a post navigation. Huh. That is really interesting because I hadn't thought about that because in my head I was thinking, well, you can just assemble a form in the background and hit sort of... and call submit on it. That works. But that cannot include files. It cannot include... Whereas with this, it's a really... That's interesting. That's really niche use case of this. But it is something that I've heard people ask for before is like I want to do a navigation with a file We encountered it with a share target. Yes. Where we wanted to test it and we had to... You wrote a form so you can test it. That is true. So if you wanted to do your own rudimentary like sharing from one site to another using normal HTTP methods, we saw with sharing before that you can do this with the native share platform but you can do it between websites using... So that should be clear. You can do a fetch request but that won't navigate your page. Yes. And whereas if you're sort of doing a share you actually kind of want to like... Navigate with a post request. With some data. Interesting. I hadn't thought about that. That's... It's going to sort of come down to like how much of... How much is this going to benefit the web? I guess... That's what I was going to bring up. So I think native lazily still takes this one home because it is pretty much literally every website. Every website has images. And you want to lazy load them. It's the right thing to do. They are, I believe, the heaviest thing on... Yeah, 50% of a page weight on average on at least an HP archive is images. Yes. And so this will mean you download less of it. Especially if you're... Because if you're just going to a page... Yeah. Just to click one of the things at the top of the page which I do all the time. Open a blog post. Oh, not interested after all. Leave. Yeah. Or even like you go to a shopping website to click the button there. But you just downloaded all of the stuff there. And the browser can cancel it. But by that time, you've already downloaded a lot. Big problem if you're on a muted connection. So are we in agreement? Yep. All right. Yeah. Have it. Go on then. All right. So this is interesting. We're going to find the next finalist. So in the semifinal, we have... That was a janky animation. We need to get... Look, this is such an old tablet that we've been doing this stuff with. And it's only because we tried to do it with a pixel book but there was some flickering thing with the camera. Oh, everywhere. Looked up. Yeah. I think we should get the... In my life. I think we should get the new like $50,000 Mac Pro. Well, and just balance and monitor here. Yeah. Okay. That should run the animation smoothly. It's not touch screen though, is it? That's... For $52,000, you still don't get touch screen. Yeah, that's actually true, isn't it? Yeah. Come on. Just throw that in. Yeah. Your machine can roll downhill. Yeah, for $400. No touch screen. Right. What are you talking about? Tendent. We've got native lazy loading versus background fetch on our old janky tablet. That doesn't... That's so old it doesn't even receive Android updates anymore. Nice. I found that this morning. Okay. Oh, this is rough. I find this really hard. So, we've got a very simple feature. Like this... As in it's simple to use. As we said, useful for pretty much every website that is in existence. One of the things I would say about this is that an interesting part of this feature, the native lazy loading thing, is the browser is actually free to apply it automatically. Is it? Yes. The default value for it is auto. And I believe... But don't many sites rely on images being loaded off screen? This is a fix I made to the spec. Yes, because I was saying, like I think there were cases where people use it for like preloading images, going to a canvas, something, something, something, something. So, the rule is, I think we came up with it, must immediately load if it's detached from the document or if it's created by JavaScript. Oh, okay. Interesting. So, if you've got a load of image tags in the out of scroll view that you're relying on lazy loading, relying on like listening for a load event on, might never fire. Interesting. So, I think we're actively monitoring that. Could it also be changed like if there's an unload listener? And no exploded loading activity. Oh, I see. Yeah, it could load it. Either way, okay, that's very interesting because that's actually, I wanted to bring it up originally, but didn't because like, can't work. But if that is the case, that would be great if this opens a path for just making the, reducing the page rate of many pages, just by making the user agent smarter. So, I was balancing that around my head. You can't do the load event detection because you might have the load event on the document element. And that would bubble, the image one bubbles or captures at least. There is ways of listening to that. Stupid. Anyway, sorry. What were you saying? Because while I was just thinking about the other thing. No, I just like it. If there is an actual path that allows us to reduce the page weight by making the user agent smarter, that's a big plus. Whereas this feature makes more downloading happen. Oh, that's an easy decision. The one that saves data rather than uses it. No, I, so, yeah, we're talking about a new capability for a set of websites that are doing up and down loads. Yes, which is a limited set. I don't want to put a number on it, but it's definitely, have I written a website where I would have used it? I don't think I have. And I'm saying that nobody has, but the things that we have written here, we wouldn't have used Backyard Fetch while we would have used Image Lays loading. Oh, yeah. This is a really tough one. Yeah, it is. You write. I'm sort of convinced myself. I don't need Backyard Fetch for my blog unless I do the thing we talked about earlier of like download all my articles, move them, whatever. And again, yeah, that's, we have small enough data, Backyard Fetch, or a fast enough connection, Backyard Fetch matters less, definitely. You would still do the right thing because you don't know how fast the connection is for your user. Things like uploading videos to YouTube or photos to Google Photos or Flickr. That's amazing that it works now. Yeah. But everyone has images. Yeah. It feels like in the second year in a row we are converging on high-level features. As a reminder, I think last year it was Skrull Snap. It was Skrull Snap. Skrull Snap. Because I'm a winner. Yeah. I don't know why I'm getting so serious about this. I'm getting really worked up, like all the rest are going to be deleted. Everyone else was fired. Especially because this is my summer. I worked on this one. And that means for the final, the final, final, final. All right. It is summer versus summer. After all your complaining in the first episode that it was just me winning, the final has come down to you versus you. Okay. And you killed my feature in the process. I did. And I am not sorry. Right. Okay. Come on. I'm going to try and forget all about that. And it's odd because some of the arguments you were making before apply again. So sharing is very much a sort of PWA feature. The use cases are niche. Navigator.share. I guess that part I can't use because that's not the new part. The new part is now images in navigator.share. When did we lose the aspect ratio thing? I feel like I used that more than native lazy loading. Aspect ratio lost against sharing. This is rubbish. This is just rubbish. What have we done? So sharing contains being able to share images to the system from the web app. And we should say specifically the sharing out is... That's what I mean because just being able to tap into the sharing part is not new. Just being able to share files out is new in 2019. So while sharing itself is cool, sharing images is a more niche use case because it doesn't happen as often. Often you say like, oh, here's my blog. Tweet it out kind of thing. So the big story here is really the sharing from native to web, which is a PWA only feature, but it's a big deal. It is. But also, again, less customers. Yeah. Yeah. A few of them background fetch I'd say. Like more things deal with like larger downloads. I think if we had sharing versus background fetch, arguably background fetch would have won, maybe. But that matchup didn't happen, so no time... I think it's... It is. I think it's native lazy loading. I think, I think, I agree. We found the feature, the best feature of... 2019. According to us. Which is the only way that matters. Which is native lazy loading. When we put this to an audience... We're going to, oh, it's going to be... Which is a video we will release at some point. At some point, January, probably. When the Christmas hats don't make sense anymore. Yeah. Well, we're not... No, I mean, at CDS. We will release the CDS version where we talked to the audience where we were not wearing Christmas stuff. It was background fetch. Did we have the same matchup? No, just the overall winner was background fetch. No, because we did it, we've done it random each time. Yeah. And I don't know how much that affects it. It could have been, by coincidence, we had the same matchup. But I still think that this was a... A lot of work. Like, the spec for this is actually really big. It was a lot of effort. That is the first time that it's an HTML attribute tapping into layout. Yeah. But it was a really good cross-browser effort as well. I think it was... I think everybody agree that this is a problem that needs solving. Yes, absolutely. Or an easier way to solve it. And there's a lot to be said for lowering the bar for doing the right thing. And I think that is something that we don't do enough in web standards. Especially with the, you know, extensible web model, a lot of time we throw out the tools and we go, off you go. And we still see many, many websites not using those tools because they're complicated because they can do lots of stuff. This is a good example of lowering that bar. And together with the aspect ratio proposal. Yes. Boom. Can we bring that in? And it's like a kind of... Can we roll it into that as an extra feature? No. I really like the aspect ratio thing. Okay, okay. Native lazy loading. There we go. We found our feature of 2019. And we will see you in 2020. That's the next... Yeah, that's the next number. 2020. See you there. Um, yes. Hello. You on the telephone? So am I speaking? How may I help you? We'd like to film an episode of two or three. Is that okay? Is it convenient for you right now, sir? So I call back later. So I get off the phone. And I'll see you in 10 minutes.