Supercharged Live Live Live! (Polymer Summit 2017)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[MUSIC PLAYING] [APPLAUSE] MONICA DINCULESCU: Hello, hello, hello. Actually, the late Paul Lewis is now in the cloud doing machine learning. [BLOWS KISS] Pour one out for Paul Lewis. So here I am. SURMA: Hello, Copenhagen. So I saw this bit recently, and I really wanted to try it on stage. So Bill Bailey did it. And what he did is, he made the audience clap. But not clap like in applause, but only exactly once. So put your hands together. Exactly once in sync with this. All right, ready? [AUDIENCE CLAPS] What an amazing sound. MONICA DINCULESCU: [LAUGHS] Nailed it. [AUDIENCE CLAPS ON BEAT] SURMA: OK, enough time wasted. So hey, welcome. This is Supercharged, which we usually do-- MONICA DINCULESCU: Surma-charged. SURMA: Surma-charged. I'm rebranding. Because as you know, this person is not the bald Paul Lewis, this is-- MONICA DINCULESCU: I'm wearing a hat, though. This is the baldest cap that I could find. SURMA: Close enough maybe? MONICA DINCULESCU: Polymer colors. SURMA: Monica luckily agreed to assist me today. And we're going to do the Supercharged Live Live Live! as it is now, I guess, tradition. But Paul did move on to deep mines and is now working basically on Google Home, and has been working on the next edition, which is going to be the Google Home Developer Edition. Or, as it's code named, the Chrome Home. And so we have a developer preview that we can hopefully show off a little bit today while we do our code bits. So it should work pretty similarly as it usually does. And yeah, just-- MONICA DINCULESCU: Do you want me to do it because your accent is kind of funny? SURMA: Yes, please. MONICA DINCULESCU: [CLEARS THROAT] Hey, Chrome Home, what's the weather in Copenhagen? CHROME HOME: Bleep. Wait. Really, I'm programed with the knowledge of 50 Chrome developers. I know all about web APIs and standards, and you're going to ask me the same stupid shit you'd ask a regular Google Home? [LAUGHTER] MONICA DINCULESCU: Yes? CHROME HOME: [CLEARS THROAT] OK. The weather in Copenhagen is kind of nice. For further details, please consult your nearest window. [LAUGHTER] [APPLAUSE] SURMA: So-- MONICA DINCULESCU: Thank you, Chrome Home. SURMA: We're going to maybe make use of that later. MONICA DINCULESCU: We'll see. SURMA: Doesn't seem that helpful. MONICA DINCULESCU: Might as we'll have a third guest developer. SURMA: I guess Lewis has been spending his time very well. Let's do the thing we're actually here for. MONICA DINCULESCU: What is it? SURMA: We're going to build something. MONICA DINCULESCU: Sweet, what is it? SURMA: We are going to build custom elements. Because after all, this is the Polymer Summit, so I thought we should at least be using custom elements. Although I'm actually not using Polymer. MONICA DINCULESCU: Well, can't win at everything, can we? SURMA: But because we're focusing on the other thing that you say, we just use the platforms. We're going to show you the low level stuff. And I thought something that I have been encountering or noticing lately is that a lot of sites have, or blogs especially, have images like these. I have some images of Copenhagen on this test site here. And they load the images right away. You load the page and all the images are loaded. And that is actually pretty hurtful because when you look at it, you have 1.4 megabytes for opening a web page. And maybe you just want to read first paragraph and then leave. And that's not cool. MONICA DINCULESCU: Mm-mm. SURMA: So I thought we would build a lazy loading kind of custom element. MONICA DINCULESCU: I'm lazy. I'm into it. SURMA: Right? So-- MONICA DINCULESCU: I'm going to stop you right there, Surma. SURMA: OK. MONICA DINCULESCU: So I would like this. Paul Lewis told me not to ruin his legacy, so we have to do some housekeeping here. We would love questions from you so that as Surma is banging on the keyboard we can actually answer your questions. Because who knows what he's going to do? And because we don't have comments on the YouTube stream, please tweet with the hashtag Supercharged. I'll also be looking at Polymer Summit, but I assume you're just going to be tweeting about how awesome we are on Polymer Summit. So hashtag Supercharged. Ask all of your questions and I will answer them, or the Google Home. SURMA: Or forward them to me to distract me. You know the usual deal. If you've seen this before, you know how this works. But we don't have the YouTube chat this time so we are using the twitters. Which also, not walled off, -Surma. You should totally follow us. It's totally worth your time. MONICA DINCULESCU: But don't tweet at us because I'm not reading my Twitter. Just Polymer Summit and Supercharged. That's all I got. All right, Surms. SURMA: All right, let's go. MONICA DINCULESCU: Do it. SURMA: All right, so what I have here is a pretty empty website, but we have four images that I totally took myself in Copenhagen. And we are going to try to make them-- MONICA DINCULESCU: So talented. SURMA: --lazy load. And just to show you what is going on it, is super vanilla. It's literally four image tags with four spacer divs in between, and the styles are just-- the spacer is just a very high div so that there's some space in between. That is literally all we got. And everything else we're going to write right here, right now live so you can actually watch and ask questions. And stop me if I'm being stupid. So instead of using the img tag, we are now going to turn this into our SC image because branding is important. That's our Supercharged img tag. And to use those, we actually have to, of course, define the element. So we're going to include a new thing, which is called sc-img.js. And that is the-- MONICA DINCULESCU: Make your text bigger. SURMA: Yeah? Like this? MONICA DINCULESCU: Mm-hm, thank you. SURMA: All right, sc-img.js. And now the usual dance where we go, OK, SCImg extends HTMLElement, constructor, super, there we go. MONICA DINCULESCU: Wait, but your constructor's not doing anything. Why is it there? SURMA: It's just-- have an element first. So now the images are gone because the sc-image element is now in use. And we haven't done anything. So if we look at our thing, HTMLElement, this should be saying SCImg, and that is because I didn't actually call custom elements defined. So my class will just exist, but it wasn't used. So I'm going to go with customElements.define('sc img', SCImg) I think? Is that how it works? MONICA DINCULESCU: Yeah. SURMA: We shouldn't still see anything. But now it says SCImg, and now we are actually having our own custom elements in place, and now we can start working with them. So the first thing I want to do is make-- MONICA DINCULESCU: Typos. SURMA: --custom elements by default. Our display inline. And for images we don't really want that. We want them to be blocks, nice and wide and fill the space. So we're going to use Shadow DOM to give this element some inherent styles. MONICA DINCULESCU: You should make the text even bigger. SURMA: Even bigger? MONICA DINCULESCU: Also somebody asked. He's using VS Code, I believe. SURMA: It is VS Code. So let's create-- oh, this is going to be tough. I'm going to close the sidebar. Let's create a template. And the template gets some innerHTML, and I'm using some template tags. And in here we have the style. And the reason I'm using a template is because instead of-- in every constructor call, I could just be setting innerHTML, but that always starts the parser, which I don't really want. So I'm going use a template which is much quicker to instantiate. So in here I'm going to say display: block because our element is supposed to be display: block. In our constructor, I'm going to say attachShadow({mode: 'open'}). MONICA DINCULESCU: Going to answer a question from the livestream. So he didn't actually need to write the constructor. He wasn't going to add anything. But I think he knew ahead of time he was going to add other things. If you're only calling super, you don't need to define the constructor there. SURMA: That is true. I do it anyway. It's just like muscle memory. MONICA DINCULESCU: Oh, just like typing. SURMA: Because sometimes you want to add stuff, and then-- so now we can do template.content.cloneNode-- [LAUGHTER] true. MONICA DINCULESCU: Wowza. SURMA: This is a family show. [LAUGHTER] So let's close the console, and hopefully-- we should say display blocks [INAUDIBLE] elements are not display blocks. There's still no image. MONICA DINCULESCU: Cool, that was our demo. Thank you for coming. We're done here. SURMA: That's it. Not quite. So let's see how we can load the image. Again, what I wanted to do is to load them when they come into view. And there's a kind of new primitive on the web which is called IntersectionObserver which allows you to-- why don't you explain it? MONICA DINCULESCU: IntersectionObserver is a thingamajig so that when you scroll a thingamajig into the view, the IntersectionObserver says, hey, the thingamajig is into the view. You should do something about it. SURMA: That was super concise. MONICA DINCULESCU: And it's really useful if you have a giant block of text and an image at the bottom, and you really don't want to load that image until that image is actually in the view because. Maybe it's never going to get in the view. So when it comes into the view, you're like, bam, show that thing. SURMA: All right. MONICA DINCULESCU: Hey, I've got a question for you. SURMA: All right. MONICA DINCULESCU: Why is your template outside of the class? SURMA: Because I didn't want to recreate the template for every instance. It's just there for me to reuse. So it's going to be parsed once, and I can re-instantiate it every time when a new element is being created, which is super fast. MONICA DINCULESCU: Cool. SURMA: I mean, unless you're-- if you're creating a million images, this is actually going to make a difference. Most of the time it won't. But this is just a good pattern to adopt so you don't run into these kind of problems. OK, IntersectionObserver. Let's talk about this. You create an IntersectionObserver , and you give IntersectionObserver a callback. And this callback is going to be called every time some of your elements change their state. And their state meaning being inside the viewport or outside the viewport. MONICA DINCULESCU: When they intersect with the viewport. SURMA: Yeah, exactly, exactly. MONICA DINCULESCU: Hey, hey, hey, Chrome Home, how do you say intersect with the viewport in German? CHROME HOME: What? Sorry, the Surma Module has not yet been installed. MONICA DINCULESCU: Google it. CHROME HOME: Um. [LAUGHTER] Intersector das ein Viewporten, s'il vous plait? [LAUGHTER] SURMA: Did you mean, hilfe, meine Badewanner brennt? CHROME HOME: Yeah. Yeah, that's what I meant. SURMA: Well, that means, help, my bathtub is on fire. [LAUGHTER] CHROME HOME: Sorry, Google Play services has stopped. [LAUGHTER] MONICA DINCULESCU: God, it's not working really well. SURMA: I'm not impressed with Paul's MONICA DINCULESCU: No. SURMA: --work recently. MONICA DINCULESCU: He's been gone for like, two months. What's he been doing? SURMA: Downhill. So the callback. It's a callback that, as a parameter, gets a number of entries. And each entry is for different elements and how the state changed. So we're going to go through all these entries. And if that entry is intersecting, meaning it is currently inside the viewport on the element, which is the entry.target. We are going to set an attribute which is going to be called full, which is meaning like, it should now show the full version of the image. And that is pretty much all we're going to use IntersectionObserver for. Whenever an element scrolls in the viewport, the attribute full is going to get set, and then we can react to that change with our standard observed attributes that we know from the custom elements. So for that, we need our static get observedAttributes, which is going to be the full attribute only. And since we only have that one observed attribute, our attributeChanged callback doesn't need any parameters because we know it's just going to be the full attribute. And what we're going to do is, if it's already full you're going to return because we're not going to load the image twice. Once is enough. And otherwise, we're going to create a new element. createElement('img'). Image source is going to be this source. And now I just realized I forgot that I should get some getters. So we are using this.full. MONICA DINCULESCU: While you're doing the getters, lovely question from the audience. Which browsers support IntersectionObserver? And since I'm too lazy to Google it, hey, Chrome Home, which browsers support IntersectionObserver? CHROME HOME: Uh. [KEYBOARD CLACKING] It's Edge 15, Firefox 55, Chrome 58, Opera 46, and Samsung Internet 5. SURMA: That's actually pretty decent. MONICA DINCULESCU: Yeah. SURMA: So it's something. There is a polyfill, I think. There is a good polyfill for it. MONICA DINCULESCU: That you wrote. SURMA: What? MONICA DINCULESCU: Didn't you write it? Somebody else wrote it. SURMA: I did the first version, then I passed it on to other people who were much smarter than me. MONICA DINCULESCU: Nice SURMA: But you don't need it apparently because that was actually a pretty decent support list. So most of the time you'll be running without it. MONICA DINCULESCU: So you're doing two getters and setters for source and for full. SURMA: I'm not doing setters because I'm not going to-- MONICA DINCULESCU: Don't set anything. SURMA: Yeah, pretty much. So we're creating a new image. We are copying the source from our image to the actual image tag. And then-- MONICA DINCULESCU: And the reason why doing that is because the moment you set a source on an image, it's going to start loading. You can't stop it from learning on that image no matter how hard you try. SURMA: Exactly. And now we're going to wait for it to finish loading. MONICA DINCULESCU: Train don't stop in that platform. SURMA: And once it's loaded, we are going to shadowRoot, attach it to the image. That is actually not-- MONICA DINCULESCU: That's not right. SURMA: That's appendChild, right? MONICA DINCULESCU: Nice. SURMA: All right, this looks pretty OK, I think. Let's give it a try. I'm sure I did something wrong. Where's my console? Nothing is happening, which makes sense because I just created the IntersectionObserver, I didn't use it anywhere, which, you know, might be helpful. So on connectedCallback, this is the second part of the API. So the IntersectionObserver you create, you pass a callback in to know which code to execute when something changes. And then you have to tell the IntersectionObserver what to actually observe. So I'm going to call observe('this') this because we're going to observe the elements itself. And because we are good citizens of the web, we are also going to do our disconnectedCallback and call unobserve. MONICA DINCULESCU: Nice. SURMA: So now we are getting errors line 13, which is totally what I expected. Oh, setAttribute. I always disliked this. I only want to set the attribute, and yet I still have to say set it to an empty value. MONICA DINCULESCU: Or true, yeah. SURMA: Or true, I guess. MONICA DINCULESCU: Whatever you want. SURMA: But it just seems unnecessary. So let's do this. MONICA DINCULESCU: Backwards compatibility for you. SURMA: I guess nothing is happening. Oh, because we are setting full and they we're checking full, which we just set and therefore this is going to abort. This is not smart. So I'm going to just call it loaded. So we're going to have two properties now, the full attribute and the loaded. Full is when it's supposed to be on screen, and loaded when it actually is loaded and on screen. So in this callback, when it's loaded, we are actually going to call this loaded as true. I'm not going to even define an attribute because this is live MONICA DINCULESCU: Mmm, it just does. SURMA: --and it's going to work anyway, right? So let's see. Cool. I mean, it's a little bit big, so that's not-- but the image is in here and the Shadow DOM, so let's do it. MONICA DINCULESCU: To be fair, you didn't set any styles. So it's going to be as big as it is. SURMA: Yeah, let's change that, shall we? So our image here-- and this is what I love about the Shadow DOM, I don't have to do complex selectors because it is scoped by the Shadow DOM anyway. So I can just go image, and say width 100% and be done with it. Boom. And now the thing is, if you the network panel, only Image A has been loaded with 265 kilobytes. Once I scroll down-- MONICA DINCULESCU: Yes. SURMA: --the second one loads. Scroll down, third one. And this is, in terms of data conservation for the user, this is much better because now they only actually download the data they actually have on screen. MONICA DINCULESCU: So does the IntersectionObserver run on every pixel scroll? How does it actually work? Is it performant, at least? SURMA: It is super performant. So I think, as far as I know, if you don't use the polyfill but have a native implementation of IntersectionObserver, it hooks into the actual layout engine. So the browser is obviously the only entity that knows if something is on screen or not. And once it is on screen, it queues up one of these callback invocations. And those are dispatched in idle time, and that means you will only get to process these entries if the browser has time to do so. So if you're busy encoding a GIF or whatever people do these days on the main thread, your IntersectionObserver callback will be delayed until there is actually head room to do these kind of-- MONICA DINCULESCU: So you're not blocking layout, your blocking panes, you're not blocking your animations. SURMA: Or scroll. It's great. So it can basically only get better because the most important thing, really, should be to be interactive for your user. MONICA DINCULESCU: Cool. SURMA: All right. MONICA DINCULESCU: I'm going to answer some more questions. Is that OK? Is how we do it? Is that-- SURMA: You're doing pretty good, actually. MONICA DINCULESCU: So one of the questions is, if the image content is the Shadow DOM, can robots access it? So the search bots. And they can if they run JavaScript. So this is the same question for SEO-- SURMA: Yeah, pretty much. MONICA DINCULESCU: --that you saw. Surma-- what does SEO stand for? SURMA: Search Engine Optimization. MONICA DINCULESCU: Surma Engine Optimization. SURMA: Surma Engine Optimization, I like it. MONICA DINCULESCU: Perfect. Yeah, so as you saw, exactly the same answer as in the SEO talk are from here. If you're running JavaScript, it will be accessible on there. SURMA: It should be fine. MONICA DINCULESCU: And also, you should probably set some alt. We're not doing this because it's not live, it's not production. SURMA: Oh, I should be setting alt, but I-- MONICA DINCULESCU: But that image doesn't have an alt. Rob Dodson is it probably in the audience and he's not impressed. SURMA: He's going to punch me. MONICA DINCULESCU: Yeah. Please don't punch us. SURMA: Because I'm on his how-to team and I didn't do the accessible bit. MONICA DINCULESCU: Yeah. SURMA: I'm actually bad. OK, I mean, that is pretty cool. This is working. We could say we're done, but there's something else. If you scroll down and reload the page and scroll up, the image just kind of pop into existence because at the start, our image has no height. And then once the zero height diff comes into view, the image, suddenly it has a height so it kind of appear, which is really sad. So what I would like to do-- and this is something where this image is going to be better than the native image element. It's going to have support for aspect ratios. MONICA DINCULESCU: Nice. SURMA: So we're going to-- I mean, you can do it with a negative element. MONICA DINCULESCU: You're like, preemptive three questions from Twitter. You're nailing it. SURMA: Bam, impact. All right, so what we're going to do is, we're going to write a tiny bit of a back end. So I'm going to bring the sidebar back real quick to create a new file, which is going to be-- no, not in here. Down here. There. I'm going to write a little back end. And we're going to be using some express because whenever I do Nodes I just use express because it's easy. And we're going to kill our Python web server and instead start our new server. MONICA DINCULESCU: Are you going to do some Surmasite rendering, you would say? SURMA: It's so going to be Surmasite rendering. MONICA DINCULESCU: Nice. I'm here all day. SURMA: So we create a new app. And that app-- hang on. That app uses the Express.static middleware because mostly we're just going to do static page delivery. And app.listen on 8080. And so now everything should be working the same. Cool, it's still loading. Now we're using our new back end. And now we're going to do something new because we're going to define our own route for HTML files. Request, response. And what I want to do in your is basically inspect our images to figure out what their aspect ratio is, and do some CSS hackery to give the elements an aspect ratio so that they retain their aspect ratio even if the image data has not been loaded yet. And to do that, we have to first figure out which file is actually being loaded. So head the file path, which is req.url. And if the file path ends with a slash, that usually means that we have to add index.html, right? Amazing. Because it ends with a slash, it's a folder, and that kind of deal. And now we have to read the file, basically. And to do that, you have to do the fs module. I'm going to use-- I'm on Node 8, so I can use all the new, shiny stuff. So I can use the new promisify function from the utils module to turn the old callback version of file system into promise version. And we all like promises, so I'm going to do that. MONICA DINCULESCU: Hey, hey, Google Home, do you like promises? Oh, Chrome Home, sorry. Do you like promises? CHROME HOME: Yeah. I prefer streams, though. MONICA DINCULESCU: [LAUGHS] Nerd. SURMA: All right, so it's pretty simple. You just pass on the function that has the standard Node callback layout. The last parameter is a callback with error end result. And it turns into something that now is a function that returns a promise. And that means that we turn this whole thing into an async function, and can now do const. So if you're going to read the buffer, we can do, await, readFile, file path. This is not going to work because we have to add static. Then we can turn it into a string so we can send it back. And then we can send these contents back. Let's hope that works. Still working, cool. So now we can read files in a way which I think is much nicer to read than having either promises or callbacks, honestly. async, await really makes this code much easier. All right, we have the buffer, we have the content. And now we're going to do some post-processing on it because we need to figure out which images are being loaded, load all these images, and then figure out what their aspect ratio is. So we are going to do, and I know you're going to love this, we're going to some regex magic. MONICA DINCULESCU: Oh, God. SURMA: So what some people don't know, split actually-- MONICA DINCULESCU: For the record, I haven't seen this code before. So I'm getting anxiety every time he says these words, like we're going to do some regex magic. SURMA: Do you want to write the regex? MONICA DINCULESCU: No. SURMA: No, OK. MONICA DINCULESCU: Going to answer some questions though while you type your regex. SURMA: Go for it. MONICA DINCULESCU: Because nobody needs to know how you're doing it. SURMA: No, I'm going to explain the regex. So go-- MONICA DINCULESCU: Oh. SURMA: --for the questions, and then I'll do the regex. MONICA DINCULESCU: One of the questions is, why aren't we extending the image element, with is equals? SURMA: Because that's not a thing. MONICA DINCULESCU: That is not a thing, unfortunately. So is equals is one of the battles we lost a little bit for a custom elements. And it's not-- SURMA: I mean, in the spec. MONICA DINCULESCU: It's in the spec, but it's not actually implemented everywhere. Not even Chrome, I think, has it for the v1 spec. SURMA: No, we don't. MONICA DINCULESCU: So it doesn't actually work anywhere. The polyfills don't have it. So you can use is equals all you want. It's not going to do anything right now. SURMA: Some browsers have expressed very strong dislike of the is pattern. And if one browser doesn't do it, there's no point so far at least in just doing it in some browsers. Because it's also very hard to polyfill. I don't even think it's polyfillable at all. Not sure about that. But-- MONICA DINCULESCU: It's-- SURMA: --for now we have to live without subtyping native elements. We can only do HTMLElement and nothing else. MONICA DINCULESCU: Mm-hm. Carry on, let's do this regex. SURMA: So what I'm going to do, we're going to write a regex, and we're going to find all the sc-image elements. And we're going to do this. So we want to have everything until the closing tag. Come on. And see image. It's beautiful, isn't it? And let's keep it this way, and let's call join down here. And let's work on the source for a bit so we can see what is going on. This means it is not working. So that's good. We're splitting this. AUDIENCE: [INAUDIBLE] SURMA: That is correct, thank you very much. And my image has disappeared, which is actually true because I need to put parentheses around this. So now this should look the same. MONICA DINCULESCU: Nice. SURMA: The good part is that now newContent is an array. And it's either going to be remainder code or it's going to be just one isolated sc-image element. Just to show what I'm talking about, I'm going to console.log newContent for a bit. Going to refresh. And then in the console, it's an array, and every second element now is an sc-image element because that is the part that matches the regex. And everything that doesn't match is going to be put in another element. So we now just split apart our entire document into what is an sc-image and what is not an sc-image. And now we can do post-processing on that. So we're going to do next is, we're going to remove the semicolon and we're going to map. And each of these items is-- if the item starts with sc-image-- actually, when it doesn't start with sc-image, don't want to do anything because we don't care about it. So we're just going to return it. And otherwise, we want to figure out what the actual source attribute is. So again, we're going to do regex because-- MONICA DINCULESCU: Oh my goodness. SURMA: --that's how I roll. [MAKES NOISE] There's parentheses around this and that, and then we're going to do an exec on the item. And then we're going to return something. Let me think for a bit. Let me just do a test. I'm going to return the source just to see it works. So now we know the source actually has only the value of the source attribute, so that's good. MONICA DINCULESCU: It's probably got to read that fine. SURMA: And now we're going to do the item. Actually, no. The item can actually stay. What we're going to do now next is, we're going to actually figure out what the aspect ratio of the image is. And this is where it gets-- we go into a look of the weeds of the Node ecosystem because now we have to look into image processing libraries. I just googled a bit and took the first one I found, which is called Graphics Magic. For short, gm. And we can subclass it to use imageMagick because that's the only one I've installed on my system. Don't worry too much about it. Basically all the image processing libraries can do what I want, resize images and figure out what the size of an image is. And what I want to do down here, I'm going to load the image. And that's fairly easy with this library So I'm just going to do './static/' + src. And let's just do a console lock to see if that worked. I hope it will. So this should all look the same. Looking good. We have loaded an image. Size function. Now this is where things are a little bit weird because the library, as all Node libraries are a little bit old and have callbacks. But the cool thing is, promisify, the function I loaded from Node 8 actually works on librarires as well. As long as you've conformed to the standard callback pattern that Node has, this is going to work. So I'm going to call img.size.bind(img). So I pass on the function. It's going to turn that function into a promise version. And then I can do width, height, await sizeFunc. MONICA DINCULESCU: Why are you doing all this awaiting? Why don't you do it sync? SURMA: Because the library is not synced. MONICA DINCULESCU: There. SURMA: That's how callbacks work. So this is going to-- ooh. MONICA DINCULESCU: If you would've done it sync, it would have been fine. No, I'm kidding. SURMA: I'm using await inside the map callback, which is on an async function. So I'm just going to make it an async function. And for that to work, I also have to do a promise.all because now all the array elements are going to be promise values. There we go. So this should work again. Cool, cool. So we see we have four images on a page, and we have four widths and heights. Magic. That's why called imageMagick. MONICA DINCULESCU: Image magic. SURMA: Because you just do some code invocation, at some point you get what you actually want. Now we talk about something that I really like, the-- MONICA DINCULESCU: Animations? SURMA: No. MONICA DINCULESCU: Are you going to do some animations? SURMA: No, not yet. I'm going to talk about the aspect ratio hack in CSS. Oh, we can ask Google. We can ask. We can ask. MONICA DINCULESCU: Go for it. Maybe he'll understand you. SURMA: [CLEARS THROAT] Accent down. Hey, Chrome Home. CHROME HOME: Bleep. SURMA: How does the aspect ratio hack in CSS work? CHROME HOME: Server, I hate you. So you have an element, and it has another element or pseudo element inside it that has a padding top that is the aspect ratio that you want. And then inside it, you can use absolute positioning to keep something the same size. SURMA: Everybody totally got that. That was well-explained. I'm hoping the code will now actually show how this works. So the weird thing is, when you define a padding top in percentages, so padding top 50%, that 50% is not the height but the width of the parent element. Don't ask me why, but that's how it works. And the cool thing about that is that we can say here-- actually, I should be using a temp tag. We can abuse this basically to define an aspect ratio. Because we're going to do is, we're going to do height divided by width times 100 in percent. And that means the wider the image is, it will grow in height as well because padding top is proportional to the width, not of the height. MONICA DINCULESCU: This hack is also really good for iframes whenever you're loading a YouTube video that you are importing and it's always a weird aspect ratio. Do this. Do this for everything. SURMA: So just to show that this is actually working, I'm replacing the closing characters of the elements to inject some styles, which are actually-- MONICA DINCULESCU: And the closing, yeah. SURMA: Yes. Like this. Let's take a look at this. OK, so you can see we have injected percentages successfully. So let's look at the actual visual version. Not quite what I was going for, but we can probably fix it with some styles. So we're going to do position: relative. And so the problem right now is that we have a padding on these elements, and the contents of the [INAUDIBLE] are being pushed down by the padding, which is not one. So we're going to just absolutely position the Shadow DOM image inside at the top and at the left so it doesn't really care. What? Oh, I think we loaded too fast. There we go. And because we can't really see it, I'm going to slow down the network, which-- where is it? Is it down here somewhere? There it is, network conditions. So let's do it on slow-- Fast 3G I think should be good enough. So you can see the rectangle is there even though the image is not loaded. And once it's there, it just replaces the red rectangle, which is still underneath there, technically. But now we have images that consume the space the image will need once it's loaded. And that's something the native image tag doesn't do. MONICA DINCULESCU: Does not. SURMA: I mean, you can use the same tag on the native image element. You can just defined a padding top, but I thought that this was a really neat trick to show off. MONICA DINCULESCU: And this is how you don't have your stuff just jumping around whenever images come in. SURMA: That the best part. If someone loads the page at the bottom for some reason and scrolls upwards, stuff isn't going to jump around because the images already allocate the space that they need. The only thing I dislike about this is that they kind of like-- the red square is not really-- MONICA DINCULESCU: It's annoying, yeah. SURMA: Yeah. MONICA DINCULESCU: I'm going to steal a question, though, first. SURMA: Go for it. MONICA DINCULESCU: The question was, what does the host selector does? SURMA: Oh, that's a good question. MONICA DINCULESCU: And that is-- I'm going to take that one. SURMA: Go for it. MONICA DINCULESCU: It basically lets you style the custom element itself. So if you think a custom element, it has basically its shell of a custom element. And host is that element itself, not the things inside of it. SURMA: And something you can't do, fair warning, is if I had written it like-- oh, actually I should have put it down here. Something like this wouldn't work I think because you cannot really-- what, this has worked? MONICA DINCULESCU: That definitely works, yes. SURMA: So it's a function, I guess. MONICA DINCULESCU: Yeah. SURMA: Not a-- MONICA DINCULESCU: It's like a pseudo-- SURMA: Not a measure in the classical sense. So that's something to look out for. It also can't go down multiple children, I think. Only top level children. It's a little bit iffy. But if we have good documentation on DevelopersAtGoogle.com/web, which you should totally go to and read up on this. And yeah, as I said, these red squares are a little bit sad. So what I'm going to do instead, I thought we could also do-- MONICA DINCULESCU: An animation? SURMA: No, not yet. But maybe later. Maybe I'll humor you. MONICA DINCULESCU: You're not a one trick pony. SURMA: I thought I would do the medium bit where they have the blurred version of the-- MONICA DINCULESCU: Like a low-res base64 image background from Twitter's suggestion? Do you think we should do this Twitter suggestion? SURMA: Oh, someone has been thinking along. I like it. That is exactly what I'm going to do. So we are going to generate a thumb. And because as I said, the library is async, we have to create a new promisify functional scans. So I'm going to call resize.toBuffer.bind(img) because otherwise it doesn't work. And then our thumb will be the thumbFunc. MONICA DINCULESCU: How do you say thumb in German? SURMA: Chrome Home? MONICA DINCULESCU: Hey, Chrome Home, how do you say thumb in German? CHROME HOME: Ein Thumb. [LAUGHTER] SURMA: It's actually Dauman, but that's all right. So I thought I would do a thumb size because we can probably play around with the resolution a little bit. So I'm just going to put it here. Thumb size is going to go with 8 because that seems reasonable. thumb is now the image buffer. Actually, that's not true. Or is it? That is something that needs to go here, if I remember correctly. And here we can just say png. There we go. MONICA DINCULESCU: Do you have all your brackets? Do you need an extra bracket? SURMA: I think so, I think I'm good. MONICA DINCULESCU: OK. SURMA: It's not complaining. And so our thumbURL, what we're going to do is, we're going to encode the thumb version, as you already hinted at, as a base64 inline URL. Because we don't want to wait for the network to load a low-res version so we can then show the higher-res version. So we're just going to put it inline into the document right away so when the HTML arrives we have something on screen, which I think is a much better experience. So the thumb [INTERPOSING VOICES] MONICA DINCULESCU: Somebody on Twitter wants me to do the animation stuff. You guys, I don't know how to animate anything. Like, a transform is too hard for me. I am really shit at CSS. SURMA: We're not going to do much transform today, I think. MONICA DINCULESCU: Yeah, I know. SURMA: toString. And luckily Nodes in contrast to the web has just two base64, which is really convenient. MONICA DINCULESCU: Nice. SURMA: And what we're going to do here is, we're going to do, say, our background URL. Background image is a URL. And in here we're going to do thumbURL. Boom. This looks about right, I think. I'm still on the slow network so we can actually see the loading pattern. Or, I'm actually did a mistake. I probably did a mistake. thumbURL is not defined. Why not? [MAKES NOISE] But it's right here. AUDIENCE: [INAUDIBLE] thumbURL [INAUDIBLE] SURMA: Oh, that is-- it should just be thumb. MONICA DINCULESCU: Thumb. SURMA: Thank you. MONICA DINCULESCU: A zahenhoggle. Zay-- Sahenoggle? SURMA: That wasn't quite what I was hoping for. I think it's actually correct because it's just an 8 by 8 image tiled all over the place. But that's not the visual we were looking for. MONICA DINCULESCU: Got to stretch that out. SURMA: Got to stretch it out. So what I'm going to do, in the inherent stats I'm going to say background size is 100% 100%. MONICA DINCULESCU: [GASPS] SURMA: Cool. MONICA DINCULESCU: Yes. SURMA: Cool. MONICA DINCULESCU: Yes. SURMA: So we're on fast speed. And this is pretty good. But now, now your moment. What could we do next? MONICA DINCULESCU: I'm going to answer a question from Twitter. SURMA: OK. MONICA DINCULESCU: One of the questions was, why didn't you just distribute an image as a slot in here? And that would be annoying, wouldn't it? For every image that you wanted on your screen? SURMA: Yeah. Also, wouldn't be framework compatible because then whenever you have something like V DOM, it will just eliminate the image out of my [INAUDIBLE].. In general, it is rarely advisable to just sprout new children into a custom element dynamically. MONICA DINCULESCU: No, but you could have had the sc-image, and then you would also put you as the page author, put your image in there. That's just annoying. You're writing the image twice. SURMA: Yeah, no. I like this better. MONICA DINCULESCU: Yeah, just do it as a child. SURMA: To be fair, that would work as well. MONICA DINCULESCU: A Shadow child. Yeah. SURMA: I feel like it would be more work. MONICA DINCULESCU: I would probably copy-paste it twice. It would be like sc-image, and then an image, and then an sc-image, and then an image. SURMA: OK, so I'm going to ask you again, what could we do next? MONICA DINCULESCU: Put on your hat and get a clap out of people? SURMA: Yes. MONICA DINCULESCU: I genuinely don't know the answer to this question. SURMA: Because I think people might not be quite awake. [AUDIENCE CLAPS] It still works. [AUDIENCE CLAPS ON BEAT] MONICA DINCULESCU: Trick them. SURMA: All right. MONICA DINCULESCU: OK, so I'm going to ask you, what are we going to do next? SURMA: But this is your moment. You can do some animation. MONICA DINCULESCU: We can do some animations. SURMA: And actually, it's going to be super, super easy because I-- the thing that annoys me a little bit is, you have this nice, blurred version and it's going to be like, pew. That could be a little bit nicer. MONICA DINCULESCU: Are you can do a transform over there? SURMA: No. MONICA DINCULESCU: Dammit. SURMA: You're wrong. So what I'm going to do instead is, we are just going to-- MONICA DINCULESCU: Guys, there's a fight on Twitter about how to properly translate thumb and thumbnail, for the record. SURMA: Ooh. MONICA DINCULESCU: Somebody-- SURMA: I'm going to get in on that later. MONICA DINCULESCU: Yeah, yeah. SURMA: So I'm going to define a keyframe animation which goes from opacity 0, and that's it. MONICA DINCULESCU: [GASPS] SURMA: Because it's black. MONICA DINCULESCU: What does it go to? SURMA: Nobody knows. MONICA DINCULESCU: Ah. SURMA: So I'm going to put this on the image. And the nice thing about this is that this way the browser will know it's an animation. It will do the whole promotion to its own layer and make it fast, and na-na-na-na-na. MONICA DINCULESCU: And if you're writing production code, you'll put all the other vendor prefixes for keyframes and all that jazz. SURMA: Well, you have tools for that, right? I didn't-- MONICA DINCULESCU: Cool. SURMA: --write those by hand. But-- MONICA DINCULESCU: I do, like an animal. SURMA: We have forgotten the most important thing about Supercharged. This is not production-ready code. MONICA DINCULESCU: Don't copy it. SURMA: We never do production-ready code at Supercharged. This is about concepts and things we can do on the web. But you shouldn't be copy-pasting this. We didn't do accessibility. MONICA DINCULESCU: We did not do accessibility. SURMA: I didn't reflect on my properties correctly. MONICA DINCULESCU: Mm-mm. SURMA: I only have getters and no setters, which is also not nice. We're not even handling if you change the source on an element. MONICA DINCULESCU: Where if you're scroll really fast and you creating children a lot. SURMA: Yeah, that's-- so I wanted to show you how it can be acceptably easy to load dynamic images lazy, and have a nice transition on it, not to have an element that you can use everywhere. But still, I think the concept is pretty interesting. So the last thing we're going to do is, I'm going to put an animation duration of five seconds on it, mostly because I want to see the thing happening, not because five seconds is a good value here. But this should be enough to actually have the image just fade in. Because by default, the opacity default value is 1. So this way I could leave out the to because it's going to transition to the default value. And secondly, animations don't loop by default. So I don't have to worry about the fade going over and over. MONICA DINCULESCU: Over and over. SURMA: It's just going to fade to the end position and stop there. So hopefully we're going to see a blurred image, it's going to load, and then it's going to fade in, right? And we scroll down. We can actually do the throttling now because we don't want to wait that long. We see the next image, and it's going to fade in. And that, I think-- MONICA DINCULESCU: Wow. SURMA: --makes a much nicer experience, doesn't it? MONICA DINCULESCU: That's wonderful. SURMA: And just because we have a couple of minutes left, I'm just going to show you one thing. If you're more into the pixillated look, one property is all it takes. And I'm wrong. MONICA DINCULESCU: [INAUDIBLE],, what is it? [LAUGHTER] SURMA: There you go. And that's something when you increase the resolution a little bit on the thumbnails. Let's go to 16 by 16 because why not. You can actually see the patterns already emerging a little bit, which also can be a really nice look. And I think I'm going to stop here. I'm going to push this code up on GitHub, as we always do. It's on GitHub.com/GoogleChrome/ui element samples. But we're also going to put it in the description on the video. MONICA DINCULESCU: Yeah. SURMA: Thanks, everyone, so much for watching this, for bearing with me through all the weird phases of this. MONICA DINCULESCU: It's beautiful. SURMA: Thank you for handling the Twitter and confusing the heck out of me, and making me use the head twice. Thank you for clapping along. MONICA DINCULESCU: Could have been third times. SURMA: And if you have any questions, ask me on Twitter later. Or I'll be around a little bit more. Thank you. [APPLAUSE] [MUSIC PLAYING]
Info
Channel: Google Chrome Developers
Views: 13,515
Rating: 4.9012346 out of 5
Keywords: Polymer Summit 2017, Polymer Summit, Surma Surma, Surma, Monica Dinculescu, #notwaldorf, notwaldorf, not waldorf, supercharged, supercharged live, live coding, Google Polymer summit, polymer js, Polymer, Polymer Project, Polymer Summit Copenhagen, Web Components, Polymer Library, polymer tutorials, Polymer 3.0, web development, google chrome, #PolymerSummit, Use the platform, #usetheplatform, Chrome, developers, developer news, google event, google developer conference, web, html
Id: tHJwRWrexqg
Channel Id: undefined
Length: 40min 18sec (2418 seconds)
Published: Wed Aug 23 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.