115 matches found
Importing vs fetching JSON
This year, JSON module imports became baseline 'newly available', meaning they're implemented across browser engines. import data from './data.json' with type: 'json' ; // And… const default: data = await import'./data.json', with: type: 'json' , ; I'm glad JavaScript has this feature, but I can'...
The present and potential future of progressive image rendering
Progressive image formats allow the decoder to create a partial rendering when only part of the image resource is available. Sometimes it's part of the image, and sometimes it's a low quality/resolution version of the image. I've been digging into it recently, and I think there are some common...
Fetch streams are great, but not for measuring upload/download progress
Part of my role at Mozilla is making sure we're focusing on the right features, and we got onto the topic of fetch upload streams. It's something Chrome has supported for a while, but it isn't yet supported in either Firefox or Safari. I asked folks on various social platforms what they thought o...
Making XML human-readable without XSLT
Ok. This one is niche. But heh, you might enjoy a dive into this esoteric corner of the web – I certainly did. XSLT and browser support I want to get to the technical-fun bits quickly, so here's a quick rundown: XSLT is an XML language for transforming XML, including transforming it into non-XML...
Give footnotes the boot
I hate footnotes1, and hopefully by the end of this, you will too. Let's get down to it… The UX of footnotes in printed media You, the reader, encounter a tiny number2 within some prose. This indicates to you that I, the writer, have something more to say on this topic. And, for your inconvenienc...
Animating zooming using CSS: transform order is important… sometimes
I was using Discord the other day. I tapped to zoom into an image, and it animated in an odd way that I'd seen before. Like this: Notice how it kinda 'swoops' into the wildcat's face, rather than zooming straight in? See how the right-hand side of the cat's head goes out-of-frame, and then back i...
Firefox + custom elements + iframes bug
Over at Shopify we've been building a bunch of web components to use internally and in third party contexts. All of a sudden, we found some strange errors in our logs, all from Firefox. This is the post I wish existed when we discovered it. The bug The bug happens when a custom element or web...
How should <selectedoption> work?
We're finally getting a way to fully style & customise elements! But there's a detail I'd like everyone's opinion on. Update: Your feedback was heard, and folks have agreed to change the behaviour here. See the update below. A brief intro to customisable If you want to hear about it in depth, I...
How should work?
We're finally getting a way to fully style & customise elements! But there's a detail I'd like everyone's opinion on. A brief intro to customisable If you want to hear about it in depth, I talked about it on OTMT, and there's a great post by Una Kravets. But here's a whirlwind tour: / Opt in to t...
Video with alpha transparency on the web
I've been helping some teams at Shopify improve page load performance, and the issue of 'videos with an alpha channel' kept coming up, where videos of UI mocks needed to be composited on top of inconsistent backgrounds, such as larger CSS backgrounds. Often a good solution here is to create the...
Video with alpha transparency on the web
I've been helping some teams at Shopify improve page load performance, and the issue of 'videos with an alpha channel' kept coming up, where videos of UI mocks needed to be composited on top of inconsistent backgrounds, such as larger CSS backgrounds. Often a good solution here is to create the...
Garbage collection and closures
Me, Surma, and Jason were hacking on a thing, and discovered that garbage collection within a function doesn't quite work how we expected. function demo const bigArrayBuffer = new ArrayBuffer100000000; const id = setTimeout = console.logbigArrayBuffer.byteLength; , 1000; return = clearTimeoutid;...
Garbage collection and closures
Me, Surma, and Jason were hacking on a thing, and discovered that garbage collection within a function doesn't quite work how we expected. function demo const bigArrayBuffer = new ArrayBuffer100000000; const id = setTimeout = console.logbigArrayBuffer.byteLength; , 1000; return = clearTimeoutid;...
HTML attributes vs DOM properties
Attributes and properties are fundamentally different things. You can have an attribute and property of the same name set to different values. For example: … const div = document.querySelector'divfoo=bar'; console.logdiv.getAttribute'foo'; // 'bar' console.logdiv.foo; // undefined div.foo = 'hell...
HTML attributes vs DOM properties
Attributes and properties are fundamentally different things. You can have an attribute and property of the same name set to different values. For example: … const div = document.querySelector'divfoo=bar'; console.logdiv.getAttribute'foo'; // 'bar' console.logdiv.foo; // undefined div.foo = 'hell...
View transitions: Handling aspect ratio changes
This post assumes some knowledge of view transitions. If you're looking for a from-scratch intro to the feature, see this article. When folks ask me for help with view transition animations that "don't quite look right", it's usually because the content changes aspect ratio. Here's how to handle...
View transitions: Handling aspect ratio changes
This post assumes some knowledge of view transitions. If you're looking for a from-scratch intro to the feature, see this article. When folks ask me for help with view transition animations that "don't quite look right", it's usually because the content changes aspect ratio. Here's how to handle...
The case against self-closing tags in HTML
Let's talk about /: You'll see this syntax on my blog because it's what Prettier does, and I really like Prettier. However, I don't think / is a good thing. First up: The facts Enter XHTML Back in the late 90s and early 2000s, the W3C had a real thing for XML, and thought that it should replace...
The case against self-closing tags in HTML
Let's talk about /: You'll see this syntax on my blog because it's what Prettier does, and I really like Prettier. However, I don't think / is a good thing. First up: The facts Enter XHTML Back in the late 90s and early 2000s, the W3C had a real thing for XML, and thought that it should replace...
The gotcha of unhandled promise rejections
Let's say you wanted to display a bunch of chapters on the page, and for whatever reason, the API only gives you a chapter at a time. You could do this: async function showChapterschapterURLs for const url of chapterURLs const response = await fetchurl; const chapterData = await response.json;...
The gotcha of unhandled promise rejections
Let's say you wanted to display a bunch of chapters on the page, and for whatever reason, the API only gives you a chapter at a time. You could do this: async function showChapterschapterURLs for const url of chapterURLs const response = await fetchurl; const chapterData = await response.json;...
Getting the correct HTML codecs parameter for an AV1 video
This post is mostly for my own reference, but I couldn't find a good guide elsewhere, so here we go! I wanted to embed a screencast in a web page, and I wanted it to be as efficient as possible. To achieve this, I created two version of the video, and embedded it like this: The MP4 version uses t...
Getting the correct HTML codecs parameter for an AV1 video
This post is mostly for my own reference, but I couldn't find a good guide elsewhere, so here we go! I wanted to embed a screencast in a web page, and I wanted it to be as efficient as possible. To achieve this, I created two version of the video, and embedded it like this: The MP4 version uses t...
Drawing a star with DOMMatrix
I recently recorded an episode of HTTP 203 on DOMPoint and DOMMatrix. If you'd rather watch the video version, here it is, but come back here for some bonus details on a silly mistake I made, which I almost got away with. DOMMatrix lets you apply transformations to DOMPoints. I find these APIs...
Drawing a star with DOMMatrix
I recently recorded an episode of HTTP 203 on DOMPoint and DOMMatrix. If you'd rather watch the video version, here it is, but come back here for some bonus details on a silly mistake I made, which I almost got away with. DOMMatrix lets you apply transformations to DOMPoints. I find these APIs...
Avoiding <img /> layout shifts: aspect-ratio vs width & height attributes
By default, an takes up zero space until the browser loads enough of the image to know its dimensions: &origin=source&to=/c/senna-d1c8a036.jpg When you run the demo, you'll see the immediately. Then, after a few seconds, this paragraph and subsequent page content shifts downwards to make room for...
Avoiding <img> layout shifts: aspect-ratio vs width & height attributes
By default, an takes up zero space until the browser loads enough of the image to know its dimensions: &origin=source&to=/c/senna-d1c8a036.jpg When you run the demo, you'll see the immediately. Then, after a few seconds, this paragraph and subsequent page content shifts downwards to make room for...
Cross-fading any two DOM elements is currently impossible
Update: A spec change has landed to make this possible, it'll ship in Chrome 100, it's been implemented in Firefox, and it already existed as a non-standard feature in Safari. Soon this feature will be supported across all major browsers! Ok, it isn't always impossible. Be amazed as I cross-fade...
How to win at CORS
CORS Cross-Origin Resource Sharing is hard. It's hard because it's part of how browsers fetch stuff, and that's a set of behaviours that started with the very first web browser over thirty years ago. Since then, it's been a constant source of development; adding features, improving defaults, and...
Writing great alt text: Emotion matters
If you prefer videos to articles, there's an episode of HTTP 203 on this topic. Ok, on with the article… Good alt text means that screen reader users get the same 'meaning' from the page as a fully sighted user. But sometimes that's easier said than done. I recently got stuck trying to figure out...
`export default thing` is different to `export { thing as default }`
Dominic Elm DM'd me on Twitter to ask me questions about circular dependencies, and, well, I didn't know the answer. After some testing, discussion, and ahem chatting to the V8 team, we figured it out, but I learned something new about JavaScript along the way. I'm going to leave the circular...
Encoding data for POST requests
Right now, when you go to copilot.github.com you're greeted with this example: async function isPositivetext const response = await fetchhttp://text-processing.com/api/sentiment/, method: 'POST', body: text=$text, headers: 'Content-Type': 'application/x-www-form-urlencoded', , ; const json = awai...
In JS functions, the 'last' return wins
In JavaScript functions, which return wins? function test return 'one'; return 'two'; return 'three'; You might say, "well it's the first one", but I'm going to try and convince you it's the last one. Don't worry, the function above definitely returns 'one', but in this case the first return...
Halve the size of images by optimising for high density displays
A long time ago we had monitors of varying resolutions, but once we started to go beyond 1024x768, screens started to get bigger as resolution got bigger. Then full-colour web-capable mobile phones arrived, but the story was the same. They had small screens, but also small resolutions. Then in 20...
Performance-testing the Google I/O site
I've been looking at the performance of F1 websites recently, but before I dig into the last couple of teams, I figured I'd look a little closer to home, and dig into the Google I/O website. 1. Part 1: Methodology & Alpha Tauri 2. Part 2: Alfa Romeo 3. Part 3: Red Bull 4. Part 4: Williams 5. Part...
Who has the fastest F1 website in 2021? Part 8
This is part 8 in a multi-part series looking at the loading performance of F1 websites. Not interested in F1? It shouldn't matter. This is just a performance review of 10 recently-built/updated sites that have broadly the same goal, but are built by different teams, and have different performanc...
Who has the fastest F1 website in 2021? Part 7
This is part 7 in a multi-part series looking at the loading performance of F1 websites. Not interested in F1? It shouldn't matter. This is just a performance review of 10 recently-built/updated sites that have broadly the same goal, but are built by different teams, and have different performanc...
Who has the fastest F1 website in 2021? Part 6
This is part 6 in a multi-part series looking at the loading performance of F1 websites. Not interested in F1? It shouldn't matter. This is just a performance review of 10 recently-built/updated sites that have broadly the same goal, but are built by different teams, and have different performanc...
Who has the fastest F1 website in 2021? Part 5
This is part 5 in a multi-part series looking at the loading performance of F1 websites. Not interested in F1? It shouldn't matter. This is just a performance review of 10 recently-built/updated sites that have broadly the same goal, but are built by different teams, and have different performanc...
Who has the fastest F1 website in 2021? Part 4
This is part 4 in a multi-part series looking at the loading performance of F1 websites. Not interested in F1? It shouldn't matter. This is just a performance review of 10 recently-built/updated sites that have broadly the same goal, but are built by different teams, and have different performanc...
Who has the fastest F1 website in 2021? Part 3
I once spent an hour creating an F1 lights-out reaction test which went viral and was even played by F1 drivers. That sounds like a brag, and it kinda is, but now whenever I pour days or even weeks of work into something, it just seems so inefficient compared to that time I spent an hour on...
Who has the fastest F1 website in 2021? Part 2
Ohhh, you've come back for more? Excellent. I was worried it was just going to be me sat here, typing to myself. This is part 2 in a multi-part series looking at the loading performance of F1 websites. Not interested in F1? It shouldn't matter. This is just a performance review of 10...
Who has the fastest F1 website in 2021? Part 1
In 2019 I did a performance review of F1 websites, and it was fun so I figured I'd do it again, but bigger definitely and better I hope. Turns out a lot has changed in the past two years, and well, some things haven't changed. Not interested in F1? It shouldn't matter. This is just a performance...
Don't use functions as callbacks unless they're designed for it
Here's an old pattern that seems to be making a comeback: // Convert some numbers into human-readable strings: import toReadableNumber from 'some-library'; const readableNumbers = someNumbers.maptoReadableNumber; Where the implementation of toReadableNumber is like this: export function...
CSS paint API: Being predictably random
Take a look at this: Space invaders If you're using a browser that supports the CSS paint API, the element will have a 'random' pixel-art gradient in the background. But it turns out, doing random in CSS isn't as easy as it seems… Initial implementation This isn't a full tutorial on the CSS paint...
AVIF has landed
Back in ancient July I released a video that dug into how lossy and lossless image compression works and how to apply that knowledge to compress a set of different images for the web. Well, that's already out of date because AVIF has arrived. Brilliant. AVIF is a new image format derived from the...
A padlock problem
There's a difference between what the browser 🔒 means to users, vs what it means to browsers. To users, it means "the page is secure", but to the browser: The certificate dialog in Chrome …it means the "connection" is secure. This is because the security check happens as part of setting up the...
Different versions of your site can be running at the same time
It's pretty easy for a user to be running an old version of your site. Not only that, but a user could be running many different versions of your site at the same time, in different tabs, and that's kinda terrifying. For instance: 1. A user opens your site. 2. You deploy an update. 3. The user...
Event listeners and garbage collection
Imagine a bit of code like this: async function showImageSizeurl const blob = await fetchurl.thenr = r.blob; const img = await createImageBitmapblob; updateUISomehowimg.width, img.height; btn1.onclick = = showImageSizeurl1; btn2.onclick = = showImageSizeurl2; This has a race condition. If the use...
Service workers at TPAC
Last month we had a service worker meeting at the W3C TPAC conference in Fukuoka. For the first time in a few years, we focused on potential new features and behaviours. Here's a summary: Resurrection finally killed reg.unregister; If you unregister a service worker registration, it's removed fro...