Modern browsers have evolved dramatically over the past two decades, quietly absorbing many features that once required custom JavaScript or third-party libraries. In this episode, Matt and Mike explore native browser capabilities including form validation, accordions, dialogs, popovers, lazy loading, and responsive images. Along the way, they discuss why letting the browser handle more of the work can improve accessibility, performance, maintainability, and the overall developer experience - without becoming dogmatic about JavaScript.
Twenty years ago, browsers were fairly limited. If you wanted animations, modal windows, accordions, validation, lazy loading, or even rounded corners, you often needed JavaScript - or even Flash.
Fast forward to today, and the browser has quietly absorbed many of those responsibilities. HTML, CSS, and built-in browser APIs have evolved significantly, yet many developers still install packages or write custom JavaScript for features that now come built in.
It’s very easy to over-engineer a website because of the versatility of JavaScript. In its most vanilla form, JavaScript adds interactivity to the frontend - but in 2026, JavaScript has been typed through TypeScript, is available on the backend, and has a vibrant community around it that extend its capabilities into niche uses like Discord bots and mobile apps. Therefore its easy to have JavaScript overstep into areas that the browser, HTML, and/or CSS can already handle. From a functionality standpoint, having JavaScript handle these areas doesn’t affect most users. But if you’re looking for the most performant and accessible options, then avoiding JavaScript when it doesn’t need to be used is often the right call - and it’ll shrink down that codebase.
Contrary to what it seems, today's episode isn't about avoiding JavaScript. It's about understanding what the browser can already do, reducing unnecessary complexity, and choosing the right tool for the job.
JavaScript has become the default tool for so many aspects of web development that it’s easy to reach for it whenever we have a problem to solve.
Before reaching for JavaScript or another dependency, it's worth asking what the browser can already do. In many cases, built-in web platform features provide accessible, performant, and standardized solutions right out of the box.
Using HTML alone we can validate forms through specific HTML attributes including:
Browser automatically provides:
<details> and <summary>The details and summary HTML elements allow us to create accordions using just HTML. More specifically we’re creating toggleable headings that when clicked reveal additional details - perfect for FAQs, accordions, and documentation.
By using these HTML elements we benefit from:
When we pair the <details> element with the name attribute, we can create a “traditional accordion” that allows only one set of details to be open at a time. Any <details> element you want included in this “traditional accordion” should have the name attribute set to the same value.
This is FAQ 1
This is FAQ 2
This is FAQ 3
<dialog>Using the command and commandfor attributes we can open and close dialog boxes without JavaScript. If you’re worried about browser support (which is good, but not perfect) then you can always use a small amount of JavaScript
CanIUse:
Common uses for <dialog>:
Compare to making a custom dialog with a <div> or other elements:
<dialog>Popovers done via browser APIs are great for menus, tooltips, dropdowns, and even contextual UI. Little or no JavaScript needed for common interactions - including dropdown lists of links.
When we apply the popover attribute to an element, it will be invisible by default. We also need to give it an ID for the next part…
This is a native HTML Popover. Click outside of it or press Escape to close it.
…now we can build a clickable element that opens up the popover, that toggle needs the attribute popovertarget set to the value of the popover’s ID.
Native Lazy Loading
Lazy loading images is a fantastic way to help image-heavy pages and it can be done by simply setting the loading attribute to lazy. Lazy loading keeps images that are not near the viewport from loading until the viewport approaches them.
Essentially images below the fold won’t even attempt to load until the user scrolls down towards them.
Lazy loading images is great for general page performance, but it’s especially helpful for:
Art Direction with <picture>
Responsive images are commonly implemented using <img> tags with dynamic dimensions (ie 100% width) and additional modifiers like CSS media queries.
Using <picture> elements instead, we can swap out images on the fly, based on media queries - commonly set to max or min-widths. This gives us more control over the art direction of our layouts because often times we want a landscape image on large screens and then a portrait image on mobile.
The browser evaluates the media attribute just like CSS media queries - in fact the media attribute and its value are often called media queries in conversation and guides.
srcset
Thesrcset attribute provides the browser with multiple versions of an image and lets it choose the most appropriate one based on the current situation, such as the screen size, display density, or media conditions
Two common uses for srcset are:
<img> element - to serve the same image at different resolutions (performance).<source> element inside <picture> - to provide the image(s) that should be used when that <source> matches (art direction or format selection).sizes
Breakdown:
src="<https://picsum.photos/id/1067/800/500>"srcsetsrcset=" <https://picsum.photos/id/1067/400/250> 400w, <https://picsum.photos/id/1067/800/500> 800w, <https://picsum.photos/id/1067/1200/750> 1200w "sizes="(max-width: 600px) 90vw, 700px"JavaScript isn't the enemy. In fact, it's one of the reasons the modern web is so powerful. But every line of JavaScript has a cost - whether that's bundle size, maintenance, accessibility, or performance. As browsers continue to evolve, one of the most valuable skills a frontend developer can have is knowing what the platform already provides before adding another dependency.
Use JS for:
Transcript
This transcript is machine generated, there may be errors.
Matt: [00:00:00] 20 years ago. Ooh. 20 years ago, browsers were fairly limited. If you wanted animations, modal windows, accordions, validation, lazy loading, or even rounded corners, you oftentimes needed JavaScript or even Flash. Remember Flash? Adobe Flash? That's crazy. Shockwave Player and all that stuff. Well, to today, and the browser has quietly absorbed many of those responsibilities. HTML, CSS, and built-in browser APIs have evolved significantly, yet many developers still install packages or write custom JavaScript for features that now come built in. It's very easy to over-engineer a website because of the versatility of JavaScript, of course. In its most vanilla form, JavaScript adds interactivity to the front end.
But 2026, JavaScript has evolved beyond that. It has been typed through TypeScript. It's available on the back end. It has a vibrant community around it that extends its capabilities [00:01:00] into more use- niche uses, like Discord bots and mobile apps. And therefore, it's very, very easy to have JavaScript overstep into areas that the browser, maybe HTML, maybe some CSS can already handle.
Basically, that the platform can already handle. From a functionality standpoint, having JavaScript handle these areas doesn't affect most users. You, you build something, it works, the users can use it. But if you are looking for the most performant and accessible options, then avoiding JavaScript when it doesn't need to be used is often the right call, and it'll shrink down the code base, possibly significantly, depending on what you're building. Contrary to what it seems, today's episode is not about avoiding JavaScript. It's actually about understanding what the browser can already do, reducing unnecessary complexity and choosing the right tool for the job. So if this sounds interesting to you and you wanna support the show, you can go and check us out on that Patreon, leave a review or rating on your podcast app, join us in our Discord server, or [00:02:00] share this with your friends. And if you wanna get 20% off a Scrimba Pro plan, you wanna go into Scrimba, learn about front end, learn about back end, and go ahead and use that interactive media player code editor that they have, which allows you to pause the lesson, edit what the instructor is doing, and then you break the code, do whatever you wanna do, experiment, and then press play, and the lesson just keeps on trucking. Go and check them out. Again, up to 20% off a Scrimba Pro plan using our link. Our link will be in the show notes, and it'll be in the show description, and full details on how it works will be in those show notes, which are on htmlallthethings.com. All right. let's kick this episode off now. If you're watching the video version, you'll see that I've actually shared my screen here, and that's because, uh, for the first time ever, I believe, I think quite
Mikhail: Yeah
Matt: built some visual examples. I was, uh, messing around with GitHub. Uh, like, I mean, I use GitHub, but I was messing around with GitHub, organizing some notes [00:03:00] notes and kind of getting some snippets together and things, and kind of just organizing my life a little bit, and I thought, you know what? It would be kind of awesome to have a repo for HAT demos. And I thought, okay, let me put this together, and I started kind of going, and then I, I decided to do this topic here today. And lo and behold, we have some demos. So as we reach the various demos, I'll of course like stop and play with them and things like that to show you visually, and I will try d- my best to describe what's happening if you're listening to the audio version, uh, because the examples are not this sort of revolutionary state-of-the-art sort of tech.
Again, we're looking at what the platform is capable of default. So there's that. Also, I will be linking actually, um, the, the repo itself. So the repo is not very organized at the moment, but I'll link to the repo itself. I hope to use it in the future as well, so you guys can go and check it out there as well.
For a first, a, a, an HTML all the things first, a HAT first, one might
Mikhail: Oh, so are we gonna do like [00:04:00] repos for every episode now?
Matt: No, no, no. This, I called this like hat podcast examples or something, so I
Mikhail: Okay
Matt: like, yeah, like this, this folder, this directory is, you know, number 100 if it was episode 100. This is number 100. Go
in here, and then here's the examples,
Mikhail: Okay
Matt: all labeled and... I've already have this stuff for this episode labeled.
I just need to put it into a nice folder structure so that we can reuse it, 'cause I don't want like 400 repos in my account. That's gonna be, that's gonna be too
Mikhail: Oh, I see what... Yeah, so it'll be just one repo, but you w- we'll just keep adding to it. Okay, I like that. Yeah. Yeah. That's good.
Matt: links in the README or
Mikhail: Yeah
Matt: figure it out as we go, but I wanna have, like, just one repo if I
can. Hopefully maybe two if we need, I guess, but
Mikhail: Yeah.
Matt: one for now
Mikhail: Mm-hmm
Matt: But I mean, I told you, I've told you about the, the episode, I told you what this is about. This is about, again, not avoiding JavaScript.
It's about seeing how powerful the platform, uh, itself is. We actually had an episode a while ago with Christopher Nandi talking about just how powerful the platform is itself. 'Cause at the time, [00:05:00] frameworks, libraries, all this stuff was just kind of going nuts and people were... You know, they weren't even touching vanilla CSS.
It was Tailwind CSS I think was new at the time or certainly newer, and people were just like, "I'm just gonna use this from now on." And it was a, you know, a whole mess. And I wanna talk about, before we get to these examples, I wanna talk briefly about this, because JavaScript has become the default tool for so many aspects of web development that it's easy to reach for it whenever we have a problem. So if we break that down, think about this. JavaScript has become the default tool for front-end development. Now, you might say, well, Matt, in its most vanilla form, which is just running in the browser, it is literally a tool to add interactivity to web pages. Your HTML is your skeleton, your CSS is your styles and your paint, let's say, and the JavaScript is the interactive tool.
It's to add coding logic to make menus move around a bit and ma- do some coding logic. Like when I click this, this disappears. When I click that, this other thing appears, things like that. So [00:06:00] of course it's the default tool for front-end development. The problem here is though is that frameworks and libraries have normalized solving almost every UI problem with JavaScript. And so you might go in there and do, oh, I have this form, I'm just gonna go and validate this form. I'm gonna make sure that someone fills in this field, I'm gonna do that in JavaScript. You don't need to do that in JavaScript. You can do that just with an HTML attribute and the, and the, browser will handle it. Now, here's the thing. If you've gone and you've done some validation to a form or you've done a redundant thing with... Not form validation, but let's say you've made a, made a toast notification, let's say. You made a toast notification, you've made a popover or something like that- And you, you're like, "Shoot, you know, I've made it in JavaScript, you know, shoot, what do I do now? You know, do I go back? Do I fix it?" What you've done is not necessarily wrong, but it means that highlights really the, the, the problem that we need to start asking ourselves, [00:07:00] can the browser do this? browser get this done without having to reach for, reach for JavaScript? Because we're building redundant features, and even if they're small, think about a huge code base. You're adding technical debt, adding more code to download, especially large code bases. That's more code to maintain. If the browser changes how it handles forms, now you have this custom verification method on validating your form, now you gotta go in and fix it. That immediately adds more opportunities for bugs. It makes that maintain... Like it, not only is there more to maintain, it makes the maintenance more difficult, 'cause over the years, as a code base ages, you're gonna have more and more of these little things that you're doing that maybe you shouldn't be doing, and now, God, I gotta go here to fix this, I gotta go here to fix that." And then also you're potentially adding another API to learn. If you're adding NPM packages, if you're adding more and more and more to your code base, you have to know that stuff. I, mean, think about it this way. If you're using, let's say, like a [00:08:00] theme, whether it's a template of some sort or a WordPress theme or something, and you're kind of really heavily custom coding a WordPress website, just as an example. The thing here is, is that if you just need a touch of CSS, like you're using a theme for 99% of what you're doing, and you just need a touch of CSS. you decide, "No, no, no, I need to use Tailwind I need to install Tailwind CSS or some other CSS tool in order to do this simple thing and not use vanilla."
Now it's like, I have to update my WordPress. I have to update my... Or I have to update my WordPress. I have to update my theme, and now I have to make sure that this other thing that I've tacked on is also updated. does it conflict with WordPress at all? Are there any problems with that? Oh, wait, the thing I, the thing I made changed the commands I need or changed the, the style that I need, so now I gotta go in and change that, but also make sure that that's interfacing with properly.
That's a mess. That's a big mess. So it just adds yet another thing to learn. And, oh, sorry, Mike, go ahead.
Mikhail: yeah, like, uh, my-- [00:09:00] I think the browsers are getting better at this as well, um, uh, over, over the last, like... When we first started, a lot of what you're seeing here had to be handled by JavaScript. Validation was mostly JavaScript-handled because there was no built-in validator. There was a bunch of forms in, in general in HTML that just were really static, like selects and radios were very rigid in what you could do and what you couldn't do.
And as browsers, like, as, as the new, you know, new browsers came out, new specs got approved for CSS and HTML, those became better and better at being customizable. And I think lately, l- the latest spec had even, like, selects being very customizable to the point where you don't need, like, custom selects, 'cause that was, like, one of the biggest requirements for a lot of these libraries.
They had to have a custom select because the select that the HTML gives you is very rigid, and you couldn't do shit all about it. Um, now that's even being put away on how selects work and stuff like that, so [00:10:00] you can rely more on browser APIs. And the, the other thing I wanna mention here as well is we're talking about validation, we're talking about, very much talking about client-side validation.
So it's, there's a little bit of a caveat here, um, and I've done this as well now. I rely on this for client-side validation, like specifically browser APIs for client-side validation, because it's not very important. It's important for the user that they see this, this information and that from a code perspective, that's important, or from a UX perspective, that's important.
From a code perspective, client-side validation is not very important. You still, regardless of whatever you do, you'll still need server-side validation because a lot of times these are the things that are gonna be exploiting your databases. These are the things that are gonna be exploiting your, your, uh, backend infrastructure and stuff like that.
So if you don't check what's being sent in a form on your server, it, it doesn't have to be JavaScript, let me be clear, like there's plenty of different server languages. Uh, you could still get pwned very [00:11:00] easily. Uh, so in, in terms of browser stuff, yes, use it. You don't really even need any JavaScript code for the most part.
There are, again, a little bit of caveats there depending on how you validate data. Uh, but for the most part, you don't really need it. You can use all the cl- the browser APIs you want, or you can use in tandem with some, a little bit of JavaScript validation just so that you don't send spam to your server.
Um, but really on the backend is where you want your validation to actually happen, and that will require some code. So again, that's the caveat.
Matt: Very, very true, and honestly a good point because, I mean, even today I'm getting spam messages from, let's say, like old WordPress sites that
Mikhail: Mm-hmm.
Matt: I'm not paid to maintain, and I'll see, like, let's say the person was supposed to take it over, supposed to take it over as an admin, they didn't change their admin email.
That's a classic. And so I'm getting all this sort of like junk mail effectively, and I'm getting all these messages of people saying, somebody commented on this post, someone commented on this post," when I know that that original site [00:12:00] owner did not want comments. And those comments are not like, "Hey, how's it going?"
They're database commands. It'll be like select, you know, select five from this and move this to here, and they're trying to run commands inside of this form, this comment form that they're filling in. They're trying to break into this, this, these people's websites. And so, I mean, not, not good. And, and we're seeing it en masse. I don't know if you've ever worked with, uh, Wordfence before, Mike. It's a firewall for WordPress. But you get reports, and if your attack rate goes up a lot in a short amount of time, you'll get a report that says, "Hey, by the way, you're getting like 400 attacks in the last 10 minutes." And it says, "Wordfence is mitigating this.
It's stopping these attacks. However, you should be aware that you're being attacked." And these attacks come in waves. I mean, I see these comment emails come in in waves, and I've seen it with, Gravity Forms before as well with WordPress, where, uh, someone will like come in and you'll... [00:13:00] So when, when you fill in a Gravity Form, it's like a contact form or whatever form you make, but contact form's the most basic.
You make a g- you make a form in Gravity Forms. You put it out there. So people will try to run database commands. So they'll write like, "Hey, my name is Bill, and I really like your product, and I really think that you should sell me a scooter or an e-bike" or whatever the heck the thing is. And then at the bottom it's like, "By the way, select null from," and a command. And it's like, "Oh, okay, so they're trying to get, like break in." Thankfully Gravity Forms is blocking that. I also have the Wordfence is going and stuff like this. But the thing is, is it's like I see that all the time with WordPress, working with clients. And I'll see it with other things as well, it's just, uh, for, I mean, I guess for good reason, WordPress constantly under attack, and so I see that you just described, Mike, the
most there just because it's the most attacked 'cause it's one of the most popular still.
It's still, it's still kicking. It's still powering, you know, 40-some odd percent of the web or whatever the heck it is.
Mikhail: Yeah, and the, and the forms are the way that most people will do the first attacks because they're the [00:14:00] m- most susceptible. Like, this is where, like, all the SQL injections were happening, where instead of writing an email, they would wr- literally write an SQL query to drop tables, for example. And be- if,
Matt: are doing, yeah,
Mikhail: yeah, if you don't have validation on the server side, it could potentially end up in your SQL query, 'cause if you're like, for example, storing an email address, you might actually, like, put exactly that email into an SQL query to store it, right?
Like, m- like, down a couple chains, and if you're not checking for anything, it could like, instead of putting that email in, it could put drop tables in and then just drop everything
Matt: Yeah, I mean, 100%.
Mikhail: Yep
Matt: 100%. W- I'll see, I'll see them try to select a user list,
Mikhail: Yep.
Matt: that SQL injection, right?
Mikhail: Mm-hmm
Matt: to select a user list because they're trying to figure out the username. 'Cause Wordfence, for example, will tell you how many, uh, how many, how many logins failed from particular usernames, and then it will te- specifically tell you in the report, does this user exist?
And it's like, "No, no, no." 'Cause they're, they're [00:15:00] making things up, right? If it's like, I don't know, Matt's store, they'll, they'll ha- they'll try the username Matt, then they'll try Matt's store, then they'll try Matt store
admin, then admin Matt's store, and they'll keep trying these different things. And so they're just trying, trying everything.
They're trying to get as much information from your website as possible, break in, do whatever the heck they wanna do.
Mikhail: Mm-hmm.
Matt: In addition to that, though, the platform, using the browser, using, you know, the HTML, using, using th- this type of thing, th- using the platform, basically, you're, you're... What you're getting is you're getting accessibility built in. This is a big one with forms. So I've seen in the past, I mean, Mike, well, you and I've seen this, where forms s- still somewhat to, to some extent today, but certainly back in the day, they were not very customizable in terms of CSS, and so people would make their own things with divs and all the rest of it.
The problem is, is accessibility just wasn't there. You could do it. You could, with your JavaScript, with your CSS, with all your custom divs and everything else, you could make your form accessible. [00:16:00] You could add the keyboard support. You could allow the screen reader to understand what's going on. But many, many, many people would not because it's not easy, and you would often miss stuff as well.
Mikhail: That,
Matt: would miss something. "Oh, shoot, I missed the
Mikhail: yeah
Matt: here," or, "Oh, I mislabeled this," or whatever. It's not easy to do, and oftentimes it's not as good as the browser accessibility support built in anyway. And so it's better to just pass it on to the platform, especially now that we have pretty customizable forms.
It's not perfect, but it's, They're pretty customizable now
Mikhail: They're definitely getting there. And th- this is where, like, libraries like ShadCN came out, like that-- They, they came out as essentially form libraries to help you with exactly this, to, to build the primitives for a customizable form so that you didn't have to worry about the accessibility aspect of it.
'Cause the accessibility was a huge pain in the ass if you were building a custom form on top of these forms. 'Cause essentially you were just layering divs, like you're saying, on top of the actual form, so the form is still there in the background, but the divs are on top of it, so y- it had to, [00:17:00] like, still interact with the form.
Anyway, it was a nightmare. I tried to do it once, uh, without a library, and I realized why the libraries exist, and then I've used libraries ever since. But you're right. Lately, like I s- like I mentioned before, they're-- almost everything now in forms is almost fully customizable. So if you're just building a simple form, a lot of times you don't have to reach for these libraries anymore, which is cool
Matt: Yeah, you just, you just don't need to. You can, you can just pass it off. And, and what we'll cover in today's episode in a bit here is, is quite literally just, like, simple form validation. We'll be covering things like, you know, how to g- have the right type, like make sure that it's an email, min and max certain patterns, things like that Uh, also what you're getting with the browser is you have to remember that the browsers are made by a team of people, and so you're getting a whole bunch of optimizations.
So you're getting a whole bunch of b- browser optimizations, including those accessibility optimizations. But if you're, if you're using your own code, maybe having something com- like lock the scroll while taking up the whole viewport [00:18:00] is gonna be inefficient for that browser, whether that's a bug or an issue or something like that. What you want is you wanna have the most efficient way to run things. And so say you want a popover, instead of making your own popover, which is relatively simple in terms of, you know, making it work, use a, use the popover API, and that's actually easier. It's easier. You're getting the browser optimizations.
You're getting... You know, you're gonna get the most performant, uh, you know, way to do that. And if there is an issue, they have to fix it. What you're kind of doing is you're like, you're delegating the work over to them, And you're, you're pushing it over to them. You're also getting standardized behavior.
So if the person is using the browser in a certain way, maybe they're using the browser in tandem with just the keyboard, like they're, it's an accessibility thing. The browser is gonna know how their own, you know, keyboard support looks and works and things like that. So the more you delegate over to the browser, the more consistent the experience is gonna be. might add keyboard support, but maybe, I'll just off [00:19:00] the top of my head, maybe your buttons g- glow yellow or something around the edges when it has keyboard support. Meanwhile, the browser, it blo- glows red or it glows blue or something like that. just a... I'm not saying that's actually happening, just a bit of a tossaway thing.
But the th- the point is, is that you want it to be standard. Like, you want it to be clear that no, no, like this, anything that's surrounded in blue, any like button that's surrounded in blue is keyboard support from the browser. You want that standardized behavior because you don't want the person second guessing, "Wait, why is that yellow?
Is that different? Like, is it not, is it in a warning state? Is it not ready? Like, what is this?" You don't want that, right? the goal here is not to eliminate JavaScript. The goal is to let the browser do the work when it already knows what's, how to do it and what's going, and what's going on effectively. We want to delegate any work that the browser is capable of doing to the browser itself so that we don't have to create, maintain, and repair custom features. And by the way, if you create those features and the platform already supports it, you're creating redundant [00:20:00] features, and that's just a waste of time. gonna end up saving some dev time if you're able to do this effectively. So let's jump into, I think, the first part here. Uh, this, thankfully, this is a prerecorded episode, so probably going to be, gonna have to be some cuts and things like this 'cause I just realized I wanna show you the code, uh, but I'm not sharing the code. Uh, so we'll mess around with this a little bit here. I'm just gonna try to get all this up and running. Again, first time. Uh, if y- if you have any suggestions or you wanna say, Matt, you're a fool.
you don't know how to record your screen," then, uh, please, please do so now.
Mikhail: Matt, you're a fool.
Matt: Stop. Don't say that.
Uh, don't say that, Mike. put that on me Okay. So hopefully this is okay. Um, this is very first example here. Just gonna scroll down in my show note to get to my thing here. What we're gonna be doing here is we are going to take a look at some native form validation. Very, very simple, very, very easy.
Uh, you can see I have some, some [00:21:00] structured... Ooh, look at this, Mike, some structured and labeled files here, and this'll, this will be the repo. I'm gonna, I'm gonna move this around a little bit. And then, uh, we're gonna be, you know, looking at the example here. So native form validation. So the very first thing, really, really simple, is gonna be required.
I mean, quite literally, you just put a required, required attribute right in your tag, and that's just, that's... I mean, that's just straight up it. And you can see it here. So I added some styling and stuff to make this look okay,
but I mean, n- you, you don't wanna leave this empty. If you type, then immediately it is validated.
That's what the, that's what the green is for, just to, again, for visual purposes. That's what the green is for. But if you were to, you know, not leave it em- If you wanted to try to submit this, it's gonna complain at you, "Hey, please fill out this field," because this is, in fact, a required field. And this is what the browser is doing.
The browser is doing this. Now, I'm adding the green effect.
But the thing is, is the actual validation, the required field part, is actually coming from the browser, and that's, [00:22:00] you know, that's a key thing. You don't have to go in there and with your, with your JavaScript, give this input an ID and say, like, "Okay, check this ID.
Check it- check its value. Make sure that it's, make sure that it's filled in." You know, sh- stuff like that. You don't, you do not have to do this. And so just through HTML attributes alone, we're able to do a bunch of this stuff, including type email. So this is a, a very, very common thing that you would do on a form.
Uh, you would say, you know, enter your name and then enter your email. But the thing is, is their email isn't just ASDF, that's wrong. And so you can see here I have it highlighting it as, highlighting it as, uh, red. That's not right. But if I went to, like, I don't know, like matt@matt.com, now it's green. Now it's been validated.
And again,
this is the browser doing this.
Moving on here, uh, you can, can, you can control some, some numbers as well. So if you have something where, uh, a number has to be a specific thing. So you say, like, "Hey," like, "you have to enter in, like, your number of tickets," or, "You have to enter in, like, a- an age here," and the minimum age is 18, and the, the person goes [00:23:00] in there and they're like, "Oh, I'm, you know, I'm, I'm 16.
I'm 17." Well, that's unfortunately not... You know, that's not gonna fly here. And so, you know, you're not gonna be validated. Y- you have to enter a number that's higher. And so you have to enter it in, you know, 18, 19, et cetera, and you can see it'll go up, and it's all green. But if you go below 18, it's not gonna...
It actually can't even do this, but if we go, like, 16. So you can see that it's not gonna allow us to go beneath a certain thing. Same with maximum. And if we go over to here, to here, we can actually see that we're just doing this simply by adding min=18 to our, to our, uh, input here, and also max=100 to our, our input here as well.
Again, all just through the browser. If we... You know, our maximum value is, uh, 100, and we try to enter 101, it's not valid. If we try to use the arrows to go down, we can go down, but it's not gonna allow us to go higher than the 100. And then [00:24:00] this is a cool one, too, that I thought. If we scroll down here, you can see that you can use a, an attribute called pattern. Uh, so this actually allows you to use a regex. And so what I've done for this regex is I've said, "This, the person must enter in only three letters." And so if I just go, like, A, S, D, F or A... Three plus letters. Excuse me. A, S, D, F, and I keep going, it's fine. But if I go, like, 1A, S, it's not gonna work out because the numbers, the number is in there. And this is all just through the browser. You don't have to go in and have custom JavaScript and, you know, ch- check it and prevent default, and you... "Oh, I need to stop the, the form from submitting. I need to go mess with this and that." You don't have to do that. You just You just use the browser. I mean, that's it
Mikhail: Yeah. The browser does it for you, right? Like, there's still code happening, uh, th- to be clear. It's just happening at a very low level, and therefore it's running very efficiently and predictably, [00:25:00] and yeah. Like, it's... Why not take advantage of a lot of these things? Like, I, I think most people, I'm hoping, will take advantage of it.
But in the age of AI, the thing that worries me sometimes is that, like, you'll rely too much on the code, and then it'll just continue to write a bunch of gobbledygook code, and if you don't look at it and you don't check it, a lot of this stuff can be replaced with JavaScript, obviously, for no reason.
You could tell AI, like, "Hey, be accessible. Use the browser APIs," and it m- it might just give you this kinda clean code if it, if you do that
Matt: Well, the thing, the thing that, that stinks, uh, also is I've seen people, like even for just something as simple as required, I've seen people especially using no-code tools, if they try to extend the no-code tool, so if they don't know where the controls are, let's say they like go into a form creator, which is...
I mean, this is more of a software level issue, right? But if they go into a form creator and they say, "Okay, I'm gonna go and I'm gonna like put in this text box." So they get the text box going, but they don't [00:26:00] know where like the advanced settings are or wherever the settings for that box is, and they don't know how to put required.
I've seen people go in and just like p- put in some JavaScript, and in today's day and age, they'll put in some, AI-generated JavaScript, and they'll keep adding another script, another script, another script per box, and I've, I've to- absolutely seen people do this. Again, that's like kind of a niche issue, but I, mean, I've seen it in the field several times where there's just redundant...
where it's like, why did you add all this code when Webflow or WordPress or your theme or whatever it is that you're using, when it just handles it? You know, like, like pass it to the tool. Effectively, that's kind of what the point of this, this episode is, is like pass it to the tool that is, is actually gonna make it work.
You know what I mean? Like, like don't build a redundant tool. Like if, if, if if you need a hammer and it, has a hammer, then use that hammer. if there's a reason not to use the hammer, fine, but why would you go and engineer and build, manufacture a whole new hammer to then be like, just be like, "Oh- [00:27:00] Like, it does, it just makes no sense.
That makes no sense. Uh, all right, moving on to native accordions. So native accordions are something that to be constantly like a bit of a, a bit of a struggle. People would absolutely use like custom buttons. They're using ARIA labels and, and all these different things to try to, uh, help screen readers understand what is going on.
And basically what we're doing is we're using, uh, the details and the summary elements. So I'll move over to details and summary here. Uh, and you can see here that basically what you do is you have a details element, and inside, nested inside, you have a summary element, and that summary lines up with what you're seeing on the outside when the accordion is closed. And then I just have a paragraph here that
is the inside, and it's describing, in this case, what HTML is. And if you click on this, it just, it just works. It shows it to you. Again, this is built into the browser. I'm not doing anything [00:28:00] short of some styling to make it look kinda nice.
I'm just letting the browser do its thing.
I'm letting it control it. I'm letting it do whatever. And one of the biggest complaints that I hear with this feature is, "Oh, well, if I open this first one, which is what is HTML, and then I go down here and it says, 'What is JavaScript?' and I click on that, it shows both bits of information." You can actually do this, do that, do this natively too. So let me just show this. So normally what you'd want is if I click on JavaScript, the HTML to close. You can do that right here. And you can do that using the name attribute. So if we pair the details element with a, uh, with the name attribute, we can create what some people would call a traditional accordion that allows you to have only one set of details to be open. Any details element you want included in this traditional accordion should have the same name attribute set to the same value. So I'm just gonna scroll down here and you'll see this is a set. This is, this is, this is a native [00:29:00] accordion set all about HTML all the things or HAT. And you can see in the code here that my details elements have the name podcast and then I have the regular structure, the summary, I have the paragraph, and that's all I have in here.
And by allow... By putting these three with the same name, name podcast, name podcast, name podcast, now these three will operate this way. If I click on the first one, it opens, and then I click the second one, the first one will close and the second one will open.
Mikhail: I have a preference on these things, and I kinda like just leaving, letting them both be open. I, I get that it's a preference, and I understand that it's nice to have obviously both options, but like if I want to close it, I'll close it. It's not a big deal, and sometimes I wanna compare JavaScript to HTML, and it's like kind of annoying that they lock me down from doing that when they, when they use this kind of style, the name attribute.
Matt: What's interesting is I'm largely on your side too, 'cause there's sometimes where I'm trying to [00:30:00] copy and paste some information, especially if it's from an FAQ that's actually useful. Sometimes I'm like, "Oh, I wanna know how much the price is, but I also wanna know where it is," and that's two different FAQs, and I wanna just quickly jot it down.
Then it's a pain where I'm like, "Wait, it says the, you know, the admission for location one is $10 and location two is $20. Where's location one again?" And I gotta go back to the other FAQ and it's kind of a pain. However, I've heard people absolutely saying, seen it on forums and things where people say that having this sort of native, uh, a- accordion not be, you know, only one is openable at a time, they're like, "Then that, that's, that's not the functionality we need, and we still need JavaScript, so we may as well just make the whole thing with JavaScript."
And
Mikhail: I- I've, I've heard that too, yeah
Matt: And, and I don't, I don't know if that's a, a stylistic choice or whether it's like a trad- a, a traditional design choice maybe. Maybe it's a design direction. I'm not really sure what that's about, but I've, I've seen and heard the argument, so
both are available. Now, I will say, uh, [00:31:00] to Can I Use, uh, there, there might be some discrepancy with name, so just check that. I think it's widespread. I can't remember now, but I think it's slightly less, so just make sure that you have... Like, i- i- you don't care. Mm. If... You know what I mean? If you, like, really want, like, all browsers including, like, really old browsers to be able to do this native accordion thing, then unfortunately you are gonna need to use some JavaScript code All right, we're gonna move on over to native dialog boxes. Native dialogs with the dialog elements. Uh, so using, uh, the command and command four attributes, we can open and close dialog boxes without JavaScript. So let's take a look at this. So we're gonna open this up. Open and close. This is all with no JavaScript.
We're opening it and closing it. is just a little dialog, so for the listener out there, just, there's just literally a button that just says h- uh, "Open Dialog." I click it, a [00:32:00] little dialog or a little pop-up opens up, just says, "Hello, this dialog was opened without JavaScript," and there is a Close button, and that is it. So we're just gonna go on over to here
Mikhail: I'm just looking at the can I use on this and it's, it's pretty good. IE does not s- does not support it though, 'cause I
Matt: it
Mikhail: I know it only came out in the last five years. Yeah
Matt: Basically, if you have like a modern browser, you should be good, but there is gonna be some discrepancy
Mikhail: Opera Mini does not support it. That's not, in my opinion, a mo- a modern browser though, so I could, could care less.
Matt: I, sure.
Mikhail: Or could,
Matt: it's quite,
Mikhail: care less
Matt: it's, yeah, the, yeah. Fair enough. Um, anyway, so this is, this is just, I mean, a simple dialog box. Um, we can use the command and the command for attributes. Um, so basically what you do is on our open button, our open dialog button, we have a command attribute, and we set that to [00:33:00] show-modal. And then we have a command for attribute. We're setting that to myDialog. And then we have the dialog attribute itself, which is the actual pop-up, and we make sure that its ID attribute is set to myDialog, which of course control... which is controlled by the command for. They're the same. So command for is myDialog, ID is myDialog, then now the button will show the modal and close the modal. That's basically it. Very, very simple. Um, common uses for this type of thing is gonna be, uh, confirmation dialogs. Like, "Hey, did you really mean to delete this?" Uh, login prompts in some cases. Um, opening specific settings, especially advanced settings. Like, "Hey, did you really wanna go into this?" And that, that's more of a confirmation, but, "Hey, did you really wanna open up this advanced confirmations, uh, thing?" Um, or maybe it's a specific, a sp- a specific settings, maybe like a color picker shows up where you click ch- you know, "Yeah, I wanna change my color," and then a, a modal or a dialog opens up, and there you go. You can go ahead and edit away. [00:34:00] Now, the thing is, is that we're using, you know, semantic HTML with all this, of course, but we could open this up with a little bit of, uh, of JavaScript if we wanted to. Um, so I have a second example, if you will, so a dialog with JavaScript here. Um, and I'm just gonna open both of these. This is a native dialog, and this is just another example of what some people will do. Uh, this is... Now, this is because the command and command for does have a bit of CanIUse discrepancy there.
I think at, when I, checked it, it's like 78% or something allow Can I a command and command for. And so if you are worried, 'cause that's more discrepancy than the other thing I mentioned earlier. If you are worried about that discrepancy, then of course, don't, uh, don't, uh, don't use that. Use, like, a little bit of JavaScript.
But here's just an example. Um, I opened up the code here. We're still using dialog, and that's all fine. Um, but then of [00:35:00] course, when we, uh, open it with our button, we're using some JavaScript to show and, uh, show and close our, our modal, our dialog box there. So just, just an FYI, if you are working with older browsers, you may still need a small amount of JavaScript.
But as you can see here, it's a very, very small amount of JavaScript. It's not, not too crazy. If you have a modern browser, you should be fine. I wanna be clear.
Mikhail: I, I wanna pour one out for my brothers working with older browsers 'cause I can't even imagine modern web with older browsers today. We used to work with older browsers, Matt and I, for a long, long time, but
Matt: long time
Mikhail: haven't thought about an older browser in at least six years, I would say, maybe five. Um, not even once.
The only-- The, the browser trouble I have now is, like, Safari and Firefox really, and even that is, like, very, very minimal
Matt: Firefox as well, eh? I u-
Mikhail: Sometimes
Matt: that Firefox personally, at least for whate- whatever I've been doing, Firefox used to kind of be a problem-ish alongside [00:36:00] Safari, but lately Safari's been, or, uh, Firefox has been pretty good, and Safari has not, unfortunately
Mikhail: It's been equal for me. Equal issues for both Safari and Firefox
Matt: Not great.
Mikhail: Yeah. But I mean, no, it's, it-- To be clear, they, they're very minimal issues. Like, this is nothing compared to the days of yore of like IE and, uh, uh, specifically IE support. Like that, that was A nightmare. 'Cause the, the updates would roll out ev-- o-- like only when a br-- the, the actual operating system was updated.
There was no, like, software update for IE. So you would get an update once a year, and if the person didn't update their Windows from Windows XP to 7, GG. I mean, it w- I, I think after 7 they, they did roll out s- like patches with it, like during, during the 7, but it would have to be like an OS, like an operating system pa- package, a patch that would roll out the IE [00:37:00] update
Matt: I do remember IEs getting, like certainly with Windows 7, I'm just trying to remember way back to then. Like especially with Windows 7 it would be like, "Oh, I, you know, my, I got a new, I got a new like o- operating system update," and then like, you know, IE 11 appeared or whatever, whatever version it would be. Yeah. Yeah,
Mikhail: Yeah, it was, it was not great. It was not great. You have to rely on that, so people had to update their Windows, and that, this was before Windows was forcing updates, so therefore, like...
Matt: Windows Update broke back
Mikhail: Correct. Yeah. It was just a nightmare. Like, you, you would have a good pop- chunk of the population on old versions due to all this nonsense
Matt: It sucked.
Mikhail: Yeah
Matt: it just sucked. I mean, straight up
Mikhail: Mm-hmm.
Matt: Moving on here though, we're gonna move on to popovers, native popovers. Actually, I do wanna mention one, one final thing here just really quickly. So for, for these two versions of the dialog box, the one that's fully native using the command and command four attributes, and then as well as [00:38:00] this one who's, which, which is using the dialog element, uh, but then y- then using some, some JavaScript to control that with a, just a, with just a button. I just do wanna say that, uh You're still using some semantic HTML between the two, so it's still gonna be better... if you need to use this JavaScript method 'cause you are worried about an older browser, you are worried that, you know, it's only 78% or whatever it is, I'll include the Can I Use links
in the, uh, the show notes.
But if, if you're worried about that, of course go ahead and, like, you know, use a bit of JavaScript. But use as much semantic HTML as you can. Like, so for example, like you... Make sure you're still using the dialogue, s- you're still using the, the dialogue element. You're not just going ahead and being like, "Oh, the heck with all of it, I'm just gonna use a div and quickly spin this up, and then I'll add a whole bunch more JavaScript to control all that." No. Not only are you cutting down on your JavaScript, but you're also using s- again, semantic HTML, which is great for [00:39:00] passing it onto the browser, allowing for, you know, p- proper keyboard support and, like, the best accessibility that you can do. Basically, even if you do need to t- touch JavaScript, delegate as much as you can. Even just something small like that. Moving over to the popover, which is very similar to a native dialogue, but moving over to a popover. We're gonna move over here. So a popover. So popovers done via, via browser APIs are great for menus, tooltips, dropdowns, even contextual AI. Little to no JavaScript required, and in fact the ones that I have here have none.
So I have a basic popover, so there's just a button for the people listening to the episode that just says Show Popover. You click it and a little popover shows up, and it's just kinda like a d- kinda like the dialogue box where it just kind of, it just kind of popped over the whole thing. And if I click outside of this little popup, which is just includes some text, I'm gonna click out, it just goes away.
It's kinda like a lightbox, but [00:40:00] for a little bit of information. And how we did that was I have a div, which doesn't sound like semantic HTML, but I have a div here, but I have the popover attribute on it. that's... I mean, straight up, that's it. Basically to, in order to make the button that actually makes that popover show up, I have a button and I have the popover target attribute, and it is set to info-popover.
That value of needs to match the ID of the div that has the popover attribute. Uh, and that's it. Basically you connect the two via that. Again, that's just all HTML and the browser handles everything for you. Uh, one of the popular use cases I saw for, uh, popovers, um, or even dialogue boxes in some cases, but more so popovers, have been toasts. So back in the day we'd have a little toast that would pop up on your website that would say, "Hey, somebody bought this," or, "Hey, you should click this," or, "Hey, we saved your settings," or things like that. Or, users just, just booked this room. You [00:41:00] better hurry up." Things like that. Well, native popovers are, are something that I've seen be recommended for this And we can also get a little bit more fancy.
It doesn't just have to be this l- sort of lightbox design. Uh, I have another one here for an actual drop-down menu. So what I have here is a button, and again, it's just using the popover target attribute, and it's set to account-menu. And then I have a div that's filled up with links here in sort of a navbar menu type of thing. Um, if it was a nav, we would use the nav semantic HTML of course, but the... just for example purposes. So that popover target is set to account-menu. This div that contains these links has the ID account-menu and also has that popover attribute as set there. And then if you click this My Account button, it just opens up quite literally a little list of links.
And so, and you can actually play with this as well. There's ways to anchor it to a certain position, and so you could actually [00:42:00] even use this feature to some extent to have a nav menu and things like that. So this... What, what this, what this starts to allow you to do is you can actually, uh, build these things without ha- having to mess with even CSS, is the point.
Like, we're even cutting CSS out of this because with CSS it's kinda simple, but also can get kinda complicated with Z indexes. 'Cause you start going, "Oh, okay, this one will be at the top. No, no, no, this other message needs to be at the top. Oh wait, I have a privacy message that actually has to be at the top.
Oh no, this thing has to be at the top." And so you can't just easily set everything to the top. You have to have sort of a hierarchy, and so by passing things off to the browser, it makes it easier and you're not even fighting with the CSS of things. You're not worried about... Like, for example, when you click this popover, I have this small bit of information showing up in a white box in the middle, and the area around it has like a b- uh, a, a background mask. And it, it has like a bit of a transparent black. You don't have to worry about doing that. You don't have [00:43:00] to worry about having that and having it be, oh, it's not actually the full viewport height. Oh, when you scroll and the navbar disappears on mobile sometimes. Now we gotta mess with that, and we're messing around with that.
You don't have to worry about that type of stuff, and there's gonna be other little nuance concerns as well, but you don't need to worry about that. You can just use this and then boom, there you go Moving on to some image enhancements. Uh, these are various image enhancements, including some native, uh, lazy loading. Uh, so we'll go ahead and do this. I'm trying to view my show note, and Notion really wants me to see the table of contents, which goes right in front. It, one might say it even pops over The show note. Anyway, there we go. I can finally see it here. Uh, so some lazy loading here. So what, what we have here is a feature where w- we can lazy load the images. If you don't know what that is, uh, lazy loading basically says you have, let's say, a whole [00:44:00] bunch of images all over your page. Let's say your page is rather long, so the viewport is up at the top, it's showing the stuff that, of course, is above the fold as per normal.
But there's an image way down at the bottom or a collection of images way down at the bottom. What if the user never scrolls down there? Images are really heavy, much more heavy than text, much more heavy than things like that, and so you don't wanna necessarily load those images. And so you set the attribute on them to...
On the image element, you literally set the attribute loading to lazy, and then it lazy loads. It doesn't load the thing that's way, way, way, way, way down there, and you just skip it. And so in this example here, we'll just look at the code quickly. I have a whole bunch of image sources here. I have a whole bunch of them, and they're all set right here to loading lazy.
You'll also notice that I have some explicit widths and heights set. I'll explain that in a minute. But basically, what's gonna happen is if we look at the example on the left side, I have the [00:45:00] Network tab open. Now, I've disabled the cache, and I've filtered it by images, and you can see that it's only loading a 500 image here.
It's only loading some of these. If I start to scroll down, you're gonna see it f- get flooded with images. Start, it starts to load them, starts to load them, starts to load them 'cause I have a whole bunch of images here. Now, I also have this set to 3G, so you'll see how some of them are actually kind of hesitating, and they're not quite loading even though I've, I've scrolled down the viewport. This looks like it's bad UX, and you could argue it kind of is, but it's... I wanted to illustrate a point. My point is, is that lazy loading is for, is great for slow internet connections. Again, I've throttled this to 3G, which is an old mobile method more or less for mobile phones. It's very, very slow. And could you imagine a mobile phone or just someone at the speed of 3G trying to load all these images at once or even loading even more?
If you're a photographer or something and you have a huge photo gallery and it's loading all the images on [00:46:00] your page, that's gonna block loading forever. It's gonna be loading, loading, loading, loading. So it's better, in my opinion, to allow them to load in as they come so that we're able to load that first part, that above the fold quickly. But then as we scroll down, you'll can, you can see all the other images that are come f- that have come flooding in here. There is one other thing I would like to mention here too. could not get this to work. I was, like, messing with it, messing with it, messing with it, and I thought, "What the heck?" I found out that For some browsers, you have to have an explicit width and height set, and it is per browser. Otherwise, it was eagerly loading all of them. And so that's why I have an explicit height here. I'm using Microsoft Edge. Through my research, Firefox was lazy loading just with the loading attribute set to lazy, and it was doing the viewport thing. But just an FYI, if... Make sure that you have the width and height because what basically, uh, and I only did a little bit of research into this, but from what I understand it, [00:47:00] basically what the browser is doing is it's coming in and it's saying, "Okay, I'm going to...
You know, what do I need to prioritize here? Oh, you know, these images are, are, you know... I'm just gonna load them all. Like I, I don't know if they're big, they're small, they're whatever. Let's just load them all to give the user the best, the best experience." Whereas in my case, I'm like, "Hey, hang on here.
These are, these are nine hundred width images. They're, they're, they're fairly large, as we saw with the 3G hesitation. They're fairly large. Don't do that." And so you're kind of giving the browser more information to say, "Hey, th- this is the size of the images," and then the browser's gonna look and say, "Oh, these aren't like ten by ten. Best not, best not just like eagerly load them." So just an FYI, if you're really getting into the nitty-gritty of, performance, that you may need to explicitly set again the width and/or the height, have some explicit defin- uh, uh, dimensions, and just check on the browser, on the various browsers that you actually want to do your performance testing in
Mikhail: I've d- I've definitely used a ton of [00:48:00] JavaScript libraries around lazy limit lo- lo- uh, loading. Uh, so it's-- I, I haven't in a, in a long time because this came into the browser, uh, at some point, and that's been great. But I do really recommend people do this, especially if you're building for apps at scale or sites at scale.
Uh, it's not just about, like, the s- the user's experience and the user's device, it's also about bandwidth costs. So if you're loading, if you have a image-heavy website and you're not lazy loading all the images, uh, you're gonna have issues with bandwidth. Because obviously anytime a person spends time on your website, it's gonna start loading images that they're not even gonna see, and that could add up.
Like each, you know, y- you try to optimize the images as much as possible, but if you don't do that and not lazy load, yep, you might get some, uh, bad bandwidth bills
Matt: Well, a- and I, I can give you an example even, e- even if, uh... So, like, recently I set up a, a, a webpage that was for, um, more of a realtor [00:49:00] and, and they had a bunch of pictures of the, of this condo, and I mean, like, a bunch of pictures. And I, I kept telling them, "Hey, you know, no 4K images, you know, not- don't- let's not go a little crazy here."
So th- they did, to their credit, take it down from megabytes to kilobytes, but they were still rather large images, and a lot of them. And so they were throwing them in a gallery, and I was like, "Okay, like, that's, like, that's fine." But thankfully, I mean, I coulda did it with code, but thankfully the actual, uh, gallery plugin we were using just had the lazy loading option because the gallery was super far down.
Because they, what, what
had happened was the gallery was just on the edge of the fold, and so it forced everything to load. And it wasn't, like, super tragic, but what was happening, b- because it was so close to the, the view port, what was happening was they decided to move the form, the call to action form, up.
They wanted, they wanted basically the fold to have the basic description and one image, the photo gallery to no longer be second on the page, but more like third or fourth. And so now it's way down, [00:50:00] and so- It was, like, causing issues. Like, especially on, especially on mobile, like, people were definitely complaining.
They're like, "Hey, what the heck?" Because this place is also in the middle of nowhere. So what, what people were doing was, "Oh, I need to, like, you know, get more information on this place." Maybe they're going in for a viewing and they're trying to show their friend in the car or whatever, "Hey, like, take a look.
This is the place we're looking at," and they're trying to open the gallery. Now you're in the middle of nowhere, and you might be at that 3G speed. Now you have, like, a problem where you're like, "Hey, what the heck? Like, this page isn't loading. I couldn't get back in touch with you or whatever." And so you can see how, like, you know, things can kind of trickle down in that way through a, from a UX perspective. And then like you're saying, Mike, with the bandwidth, with the bandwidth cost, I mean, in this particular case, they don't have a bandwidth limitation, so that's good, or at least it's so high that it's, it's irrelevant. But if you did, why would you hand, like, hand every single user five megabytes or more for free?
Why would you do that? What's the point? So [00:51:00] that is some n- some native lazy loading. Um, that's that. I w- actually, one more thing as well. Some editors, I have seen some editors have, like, a lazy loading, know, little checkbox or, like, a toggle, and you say, "Hey, I want these images to lazy load," and they eagerly load. Check into the explicit widths and heights. Definitely check into that, 'cause I just said, like, I had to fix it for this. I was trying to get this demo to work and was like, "What the heck is going on here?" Um, and that, that ended up being the issue. Go and check, because I've went and I've checked one of my older websites, uh, and it... I checked lazy load, didn't give it a second thought, 'cause it's like, oh, this software's got it, and the software didn't have it. So definitely go and check it. Moving on to pictures, or moving away from the IMG or the image tag, on to picture. Responsive images are commonly implemented with image, right?
So what we do is we go in there and we'll, we'll set a, a dynamic dimension of 100% width and, like, you know, [00:52:00] 50 height or something like that. And then maybe if we want some more granular control, we'll use some CSS media queries where we're like, at this specific break point, I actually don't want it to be 100% width.
I want it to be just 90%, 'cause I need more room for the user's thumb to scroll by or something like that, right? Well, we can actually enhance Our responsive images, and actually more specifically, we can tackle art direction picture. So if we use the picture element instead, we can actually swap out images on the fly based upon media queries.
Now, not CSS media queries, and I'll show you that in a minute. We can commonly set, set the, uh, the min or ma- set... Sh- Jesus Murphy. We can commonly set our media queries to things like min or max widths, and this gives us more control over the art direction of our layouts because oftentimes, uh, we want a landscape image on a large screen, even on a tablet screen.
But as we shrink it down, shrink it down, shrink it down, we actually want it to be a portrait image, and so you're [00:53:00] allowing someone to have more of an art direction. When you're doing the image tag, you don't have that much capability. Like, it's, it's... You're more or less, like, squishing it, and you're trying to figure out how to squish it, and it's more about... I mean, straight up more about squishing it and less about, hey, swap in a better asset. Like, let's have better framing here. Let's, you know, w- you know, what are we doing? So let's, let's take a look at this. So we're gonna take a look This is our art direction with picture. We're going to on to this bit of code here for the person watching. what we've done here is we have a picture element. Inside of said picture element, we have, nested inside, we have multiple source elements. These source elements are where our media queries exist. These are not CSS media queries. This is where we have a media attribute, and inside of there, we're setting it to a max width.
In this case, it's max width 600, is inside of our source [00:54:00] attribute. And inside there, we also have a source set or SRC, S-E-T, for the spelling, source set attribute, and then that is set to an image. And then we have another source. So our first image there, max width 600 for the media. Now we have another image declared here, and we're saying media min width 601 with a source set that's a different image.
And then still inside the picture, we have an image tag. And the image, this allows us to have a backup in case the browser is like, "What is all this? is all this? What do we do?" Or if none of the media queries can be satisfied, the image will also appear, the image tag will also appear. So we kinda have a fallback for both of those conditions. So if we, you know, resize the browser, it should swap between both portrait and, and landscape crops. Just gonna refresh this guy here. And, uh, we're just gonna wait. I guess I shouldn't, uh, have my throttling still on here. Let me just do that. There we go. And then we're just [00:55:00] gonna keep scrolling, and you can see it changes the art direction.
So there's a... I mean, it's a terrible
Mikhail: Yeah, ask
Matt: it's just an example. Uh, there's just a walrus here, and it is a landscape image. But once we shrink, shrink, shrink, shrink, shrink, and we're below and into the 500s here in terms of pixel width, it switches to a poorly framed, hopefully you choose a, a, a well-framed, uh, image of a walrus. So there you go, a little bit of art direction. You really wanted to see the folds in this walrus' back.
Mikhail: Very good
Matt: Uh, now you might be a little bit, uh, confused here with, uh, the source set, um, or src set, if you will. This is... The source set, the attribute is used, uh, uh, provides the browser with multiple versions, uh, um, of an image, and it lets it true- choose the most appropriate one, uh, based upon the current situation, such as the screen size, display density, or other media conditions. Uh, two common uses for source set are, are on an image element to serve [00:56:00] the same image at different resolutions. Um, and this is to help with performance, which we're going to take a look at in a second. Or what we just did, you can use it on a source element, uh, inside of a picture element to provide images that should be used depending on the parameters that we just went through. So that's the next example here. We're going to be looking at source set alongside sizes inside of an image tag. So we'll take a look here. Just going to open back up my developer tools No, I won't. Okay, there we go. I was just talking to Mike actually about how the developer tools, for whatever reason on my browser, have been, like, just terrible and they wouldn't open, and that was an example of it, but thankfully it actually opened. Uh, there's... So there's that. We're gonna scroll down here, and there's our code. So inside of our image tag, normally we would just have this source, right? We have an image, we have a source attribute, and we set it to JPEG we want, right? In this case, we're just using a Pixsum, but whatever JPEG we want. But we may wanna [00:57:00] load different versions of the actual image depending on certain parameters, in this case, certain, certain sizes. Uh, so what we... The reason why we're doing this is because not only are we gonna be saving bandwidth, like a 400, you know, wide pict- uh, picture be, I'm just gonna say a megabyte.
It should be less. Let's just say a megabyte for the sake of conversation. A 400 wide, uh, picture might be one megabyte, but then, uh, you know, a super large image by comparison might be three megabytes. Well, we don't wanna hand the user those extra megabytes. We wanna keep it down just to one, and so it'll only load, you know, the certain version. So what this is, is this is not art direction like it was with the picture tag. This is not art direction. This is, you know, solely more or less for performance, uh, more, uh, basically keeping it, p- keeping the correct version of the image for the correct screen size. So inside here we have our image and we have our source, just our regular [00:58:00] src, and that is set to an image.
And then we have our source set yet again. This time there's... Inside the same attribute, we have three different images set. We have three different links. In this case it's three, uh, It's three different versions and it's, it's just three images. They're all the same picture, but they're at different sizes. And we are using yet another attribute called sizes to when these images should come in. So this is kind of gonna be weird if you're not watching, I feel like, to describe this. But basically we have our source set, and beside our first URL we have 400w, which is 400 width. We then have another URL with 800 width, and then we have another URL with 1200 width And then we have our sizes attribute, and there are three corresponding, uh, parts there.
So the sizes attribute describes how wide the image will appear in the layout. In this case, it reads if the viewport is [00:59:00] 600 pixels or smaller, this image will occupy, uh, 90, 90, uh, VW. Otherwise, it will do 700. And it... You can see as you go in, I'm gonna open up my network tab, it'll load the various versions of the image based upon where we're at.
So if I, like, really squeeze it in here and we decide to refresh, it's gonna load the 500 And if I decide to go out like this, it'll load the 750 version. So it's loading different versions, um, of the image based upon size of the viewport, more or less. And that allows you, again, to save, save, uh, save space And that's it. That's, that's it. Uh, no comments from Mike. Uh, that's, that's, that's it. I don't know. That's... Yay. It's
Mikhail: Yeah. I [01:00:00] mean, browser APIs are good. Browser APIs are good. Um, there's a lot more probably that we haven't talked about. We're not gonna be here for like eight hours talking about browser APIs, but it's something to keep in mind, something to prompt your AIs with. Just be like, "Hey, maybe prefer browser APIs versus JavaScript."
And something to learn yourself obviously, because otherwise you won't be able to tell what's good and what's bad. And this is good
Matt: Yeah, and, and again, it, this isn't, uh, you know, us trying to JavaScript. I mean, like, JavaScript is, you know, isn't the enemy here or anything like that. It's, it's actually one of the reasons why the modern web is so powerful, because it is so versatile. Uh, but the thing is, is that every single line of JavaScript does, you know, unfortunately have a cost, and it's gonna be, uh, you're gonna be paying in bundle size or maintenance or accessibility or performance, of course. And, and as the, the platform, as browsers evolve, and, uh, you know, even as we didn't really cover CSS too much today at all really, but [01:01:00] even as CSS evolves, the platform that we're building these websites on are kind of eating each other in terms of features. Like, there's several videos on YouTube where it's like, you know, CSS is eating these JavaScript features, and you should use those CSS features, for example, because JavaScript is less performant than CSS in almost all cases. Again, there's gonna be some sort of exception out there, I'm sure. But in almost all cases, and it's like hand... Like, delegate the job to the part of the platform that's capable of doing so, and don't say, "Oh, well, JavaScript's capable." It, it's, it's the, it's the all-in-one tool. Try not to give it to the all-in-one tool.
Use the all-in-one tool when you need it, and, and, like, use JavaScript for certain things. Like fetch data, of course. Authentication, uh, sure, in the back end. Uh, games, of course. You're doing complex interactions, sure. Uh, Ca- Canvas? Of course. You know, things like that. Like, if you're doing something complex that requires programming logic, then of course, go ahead and use JavaScript [01:02:00]
Mikhail: Yep. I, I think it's gonna become more relevant as time goes on. Uh, Matt and I had a couple episodes recently about how-- or, like, a web news recently, I should say, about how, like, hardware's just becoming more and more expensive. I think we're gonna start swinging back to the over-optimization, 'cause right now we're kind of in the space of like, "Hey, everything's super powerful, so you might as well just throw whatever at it.
Just throw as much JavaScript as you want, use as much memory as you want." But with devices going back to having to use eight gigabytes of RAM to even exist, uh, yeah, memory is gonna become a serious issue, and performance is gonna become a serious issue. So learning how to get the most out of your, uh, apps and your code is going to become more and more relevant.
Um, at, at least that's my theory, and there probably will be more episodes on this in the future where I might talk about how, like, to get the most out of your older [01:03:00] hardware and the most out of your perform- like, your code as well. Uh, because I, I, I see this trend starting. Like, it's not there yet, but it-- I think it's gonna be on the horizon very soon.
Matt: It's a good point. I mean, even you mentioned bandwidth. Bandwidth is absolutely on top of mind for a lot of people.
Mikhail: Mm-hmm.
Matt: Bandwidth, uh, at least at a couple of the hosts that we work with, has become 3 to 10X more expensive. And even though the limits are obviously within normal, like we're not worried about absolutely every single image, I mean, if said websites ever got super, super popular, they would absolutely blast past their, their bandwidth limitations, paying additional prices for either additional packages or even having the website crash until you update or upgrade, depending, again, on the host and the infrastructure that's in place there. I mean, computing is becoming more expensive. Things are, things are becoming more expensive through inflation and normal means as well, and it, you know, it's, it's definitely something to [01:04:00] consider. You know, being efficient basically with the resources that you have at your disposal is, is... I 100% agree, Mike.
It's, it's, it's likely the way forward. Uh, uh, maybe not even like min-maxing to, you know, the nth degree, but absolutely trying to like get a hold on things
Mikhail: Mm-hmm.
Matt: and, you know, and say, "Hey, we don't wanna just be tossing everybody five megabytes here. Let's, let's, let's take that back." Which sounds like, which sounds ridiculous, but I mean, you have
Mikhail: Yeah.
Matt: people show up it's like, well, good.
Mikhail: Mm-hmm.
Matt: know? There goes 20% of my, of my bandwidth plan, especially
Mikhail: quickly.
Matt: business. Yeah. if it's a
Mikhail: It can add up quickly.
Matt: Uh, but that's it. I think that's the episode. Let me know if you liked it. First time ever doing a demo like this. First time setting up the GitHub. Uh, probably, it was probably a bit clunky, it, uh, it being the first episode.
Probably very clunky. In fact, that's, that's the impression I have in my head.
Mikhail: Oh.
Matt: Uh, anyway, if you're interested in clunky episodes like this, [01:05:00] remember that we're on Patreon. That's patreon.com/htmlallthethings. Check out the tiers and give that a go. Many thanks to our $3 tier patrons, Tim from the Web Hacker, thewebhacker.com, Jason from Geek Life Radio via geeklifeeradio.com, Garrett Segall, Level Up Financial Planning via www.levelupfinancialplanning.com, Magnus from Yes Web via yesweb.se, Syntaxify from the HTML All the Things Discord server, and Stacy Mosler from the website swoonworthydesigns.com. And that we have a contributing author, and his name is Michael LaRocca. You can go and check out his content on our website, but also on his blog, Self-Taught: The X Generation Blog at selftaughttxg.com. And if you want to learn how to code using Scrimba's interactive media player code editor, please go and check them out.
You can get up to 20% off their Scrimba Pro plan. Full details on how it works in the show notes on htmlallthethings.com. The link to get the discount is in the show notes as well as in the show description. Feel free to leave a comment or review on the platform you're listening to this on, and we [01:06:00] are signing off