Dynamic Datalist: Autocomplete from an API :: Aaron Gustafson
Great minds think alike! I have a very similar HTML web component on the front page of The Session called input-autosuggest.
Great minds think alike! I have a very similar HTML web component on the front page of The Session called input-autosuggest.
Progressive enhancement is about building something robust, that works everywhere, and then making it better where possible.
Safari, Chrome, and Edge all allow you to install websites as though they’re apps.
On mobile Safari, this is done with the “Add to home screen” option that’s buried deep in the “share” menu, making it all but useless.
On the desktop, this is “Add to dock” in Safari, or “Install” in Chrome or Edge.
Firefox doesn’t offer this functionality, which as a shame. Firefox is my browser of choice but they decided a while back to completely abandon progressive web apps (though they might reverse that decision soon).
Anyway, being able to install websites as apps is fantastic! I’ve got a number of these “apps” in my dock: Mastodon, Bluesky, Instagram, The Session, Google Calendar, Google Meet. They all behave just like native apps. I can’t even tell which browser I used to initially install them.
If you’d like to prompt users to install your website as an app, there’s not much you can do other than show them how to do it. But that might be about to change…
I’ve been eagerly watching the proposal for a Web Install API. This would allow authors to put a button on a page that, when clicked, would trigger the installation process (the user would still need to confirm this, of course).
Right now it’s a JavaScript API called navigator.install, but there’s talk of having a declarative version too. Personally, I think this would be an ideal job for an invoker command. Making a whole new install element seems ludicrously over-engineered to me when button invoketarget="share" is right there.
Microsoft recently announced that they’d be testing the JavaScript API in an origin trial. I immediately signed up The Session for the trial. Then I updated the site to output the appropriate HTTP header.
You still need to mess around in the browser configs to test this locally. Go to edge://flags or chrome://flags/ and search for ‘Web App Installation API’, enable it and restart.
I’m now using this API on the homepage of The Session. Unsurprisingly, I’ve wrapped up the functionality into an HTML web component that I call button-install.
Here’s the code. You use it like this:
<button-install>
<button>Install the app</button>
</button-install>
Use whatever text you like inside the button.
I wasn’t sure whether to keep the button element in the regular DOM or generate it in the Shadow DOM of the custom element. Seeing as the button requires JavaScript to do anything, the Shadow DOM option would make sense. As Tess put it, Shadow DOM is for hiding your shame—the bits of your interface that depend on JavaScript.
In the end I decided to stick with a regular button element within the custom element, but I take steps to remove it when it’s not necessary.
There’s a potential issue in having an element that could self-destruct if the browser doesn’t cut the mustard. There might be a flash of seeing the button before it gets removed. That could even cause a nasty layout shift.
So far I haven’t seen this problem myself but I should probably use something like Scott’s CSS in reverse: fade in the button with a little delay (during which time the button might end up getting removed anyway).
My connectedCallback method starts by finding the button nested in the custom element:
class ButtonInstall extends HTMLElement {
connectedCallback () {
this.button = this.querySelector('button');
…
}
customElements.define('button-install', ButtonInstall);
If the navigator.install method doesn’t exist, remove the button.
if (!navigator.install) {
this.button.remove();
return;
}
If the current display-mode is standalone, then the site has already been installed, so remove the button.
if (window.matchMedia('(display-mode: standalone)').matches) {
this.button.remove();
return;
}
As an extra measure, I could also use the display-mode media query in CSS to hide the button:
@media (display-mode: standalone) {
button-install button {
display: none;
}
}
If the button has survived these tests, I can wire it up to the navigator.install method:
this.button.addEventListener('click', async (ev) => {
await navigator.install();
});
That’s all I’m doing for now. I’m not doing any try/catch stuff to handle all the permutations of what might happen next. I just hand it over to the browser from there.
Feel free to use this code if you want. Adjust the code as needed. If your manifest file says display: fullscreen you’ll need to change the test in the JavaScript accordingly.
Oh, and make sure your site already has a manifest file that has an id field in it. That’s required for navigator.install to work.
I find Brian Eno to be a fascinating chap. His music isn’t my cup of tea, but I really enjoy hearing his thoughts on art, creativity, and culture.
I’ve always loved this short piece he wrote about singing with other people. I’ve passed that link onto multiple people who have found a deep joy in singing with a choir:
Singing aloud leaves you with a sense of levity and contentedness. And then there are what I would call “civilizational benefits.” When you sing with a group of people, you learn how to subsume yourself into a group consciousness because a capella singing is all about the immersion of the self into the community. That’s one of the great feelings — to stop being me for a little while and to become us. That way lies empathy, the great social virtue.
Then there’s the whole Long Now thing, a phrase that originated with him:
I noticed that this very local attitude to space in New York paralleled a similarly limited attitude to time. Everything was exciting, fast, current, and temporary. Enormous buildings came and went, careers rose and crashed in weeks. You rarely got the feeling that anyone had the time to think two years ahead, let alone ten or a hundred. Everyone seemed to be passing through. It was undeniably lively, but the downside was that it seemed selfish, irresponsible and randomly dangerous. I came to think of this as “The Short Now”, and this suggested the possibility of its opposite - “The Long Now”.
I was listening to my Huffduffer feed recently, where I had saved yet another interview with Brian Eno. Sure enough, there was plenty of interesting food for thought, but the bit that stood out to me was relevant to, of all things, prototyping:
I have an architect friend called Rem Koolhaas. He’s a Dutch architect, and he uses this phrase, “the premature sheen.” In his architectural practice, when they first got computers and computers were first good enough to do proper renderings of things, he said everything looked amazing at first.
You could construct a building in half an hour on the computer, and you’d have this amazing-looking thing, but, he said, “It didn’t help us make good buildings. It helped us make things that looked like they might be good buildings.”
I went to visit him one day when they were working on a big new complex for some place in Texas, and they were using matchboxes and pens and packets of tissues. It was completely analog, and there was no sense at all that this had any relationship to what the final product would be, in terms of how it looked.
It meant that what you were thinking about was: How does it work? What do we want it to be like to be in that place? You started asking the important questions again, not: What kind of facing should we have on the building or what color should the stone be?
I keep thinking about that insight: “It didn’t help us make good buildings. It helped us make things that looked like they might be good buildings.”
Substitute the word “buildings” for whatever output is supposedly being revolutionised by generative models today. Websites. Articles. Public policy.
I am interested in art—we are interested in art, in any and all of its forms—because humans made it. That’s the very thing that makes it interesting; the who, the how, and especially the why.
The existence of the work itself is only part of the point, and materializing an image out of thin air misses the point of art, in very much the same way that putting a football into a Waymo to drive it up and down the street for a few hours would be entirely missing the point of sports.
An excellent example of an HTML web component from Eric:
Extend HTML to do things automatically!
He layers on the functionality and styling, considering potential gotchas at every stage. This is resilient web design in action.
There’s quite a crossover between resilience and longevity:
- Understand the requirements
- Keep scope small and fixed
- Reduce dependencies
- Produce static output
- Increase Quality Assurance
This is a wonderfully evocative description of what it was like to go online 30 years ago.
Grrr… it turns out that browsers exhibit some very frustrating behaviour when it comes to the video element. Rob has the details…
Framework monoculture is a psychology problem as much as a tech problem. When one approach becomes “how things are done,” we unconsciously defend it even when standards would give us a healthier, more interoperable ecosystem. Psychologists call this reflex System Justification.
The explains a lot about React-driven front-end development!
When a single toolset becomes the default, we don’t just prefer it, we build narratives that justify it. And that’s when a tool quietly becomes a gate or even a destructive force.
Tim recently gave a talk at Smashing Conference in New York called One Step Ahead. Based on the slides, it looks like it was an excellent talk.
Towards the end, there’s a slide that could be the tagline for Web Day Out:
Betting on the browser is our best chance at long-term success.
Most of the talk focuses on two technologies that you can add to any website with just a couple of lines of code: view transitions and speculation rules.
I’m using both of them on The Session and I can testify to their superpowers—super-snappy navigations with smooth animations.
Honestly, that takes care of 95% of the reasons for building a single-page app (the other 5% would be around managing state, which most sites—e-commerce, publishing, whatever—don’t need to bother with). Instead build a good ol’-fashioned website with pages of HTML linked together, then apply view transitions and speculation rules.
I mean, why wouldn’t you do that?
That’s not a rhetorical question. I’m genuinely interested in the reasons why people would reject a simple declarative solution in favour of the complexity of doing everything with a big JavaScript framework.
One reason might be browser support. After all, both view transitions and speculation rules are designed to be used as progressive enhancements, regardless of how many browsers happen to support them right now. If you want to attempt to have complete control, I understand why you might reach for the single-page app model, even if it means bloating the initial payload.
But think about that mindset for a second. Rather than reward the browsers that support modern features, you would instead be punishing them. You’d be treating every browser the same. Instead of taking advantage of the amazing features that some browsers have, you’d rather act as though they’re no different to legacy browsers.
I kind of understand the thinking behind that. You assume a level playing field by treating every browser as though they’re Internet Explorer. But what a waste! You ship tons of uneccesary code to perfectly capable browsers.
That could be the tagline for React.
Suppose somebody is using a blade. Perhaps they’re in the bathroom, shaving. Or maybe they’re in the kitchen, preparing food.
Suppose they cut themselves with that blade. This might have happened because the blade was too sharp. Or perhaps the blade was too dull.
Either way, it’s going to be tricky to figure out the reason just by looking at the wound.
But if you talk to the person, not only will you find out the reason, you’ll also understand their pain.
I was messing about with some images on a website recently and while I was happy enough with the arrangement on large screens, I thought it would be better to have the images in a kind of carousel on smaller screens—a swipable gallery.
My old brain immediately thought this would be fairly complicated to do, but actually it’s ludicrously straightforward. Just stick this bit of CSS on the containing element inside a media query (or better yet, a container query):
display: flex;
overflow-x: auto;
That’s it.
Oh, and you can swap out overflow-x for overflow-inline if, like me, you’re a fan of logical properties. But support for that only just landed in Safari so I’d probably wait a little while before removing the old syntax.
Here’s an example using pictures of some of the lovely people who will be speaking at Web Day Out:
While you’re at it, add this:
overscroll-behavior-inline: contain;
Thats prevents the user accidentally triggering a backwards/forwards navigation when they’re swiping.
You could add some more little niceties like this, but you don’t have to:
scroll-snap-type: inline mandatory;
scroll-behavior: smooth;
And maybe this on the individual items:
scroll-snap-align: center;
You could progressively enhance even more with the new pseudo-elements like ::scroll-button() and ::scroll-marker for Chromium browsers.
Apart from that last bit, none of this is particularly new or groundbreaking. But it was a pleasant reminder for me that interactions that used to be complicated to implement are now very straightforward indeed.
Here’s another example that Ana Tudor brought up yesterday:
You have a
sectionwith apon the left & animgon the right. How do you make theimgheight always be determined by thepwith the tiniest bit of CSS? 😼No changing the HTML structure in any way, no pseudos, no background declarations, no JS. Just a tiny bit of #CSS.
Old me would’ve said it can’t be done. But with a little bit of investigating, I found a nice straightforward solution:
section > img {
contain: size;
place-self: stretch;
object-fit: cover;
}
That’ll work whether the section has its display set to flex or grid.
There’s something very, very satisfying in finding a simple solution to something you thought would be complicated.
Honestly, I feel like web developers are constantly being gaslit into thinking that complex over-engineered solutions are the only option. When the discourse is being dominated by people invested in frameworks and libraries, all our default thinking will involve frameworks and libraries. That’s not good for users, and I don’t think it’s good for us either.
Of course, the trick is knowing that the simpler solution exists. The information probably isn’t going to fall in your lap—especially when the discourse is dominated by overly-complex JavaScript.
So get yourself a ticket for Web Day Out. It’s on Thursday, March 12th, 2026 right here in Brighton.
I guarantee you’ll hear about some magnificent techniques that will allow you to rip out plenty of complex code in favour of letting the browser do the work.
Stick with this. It’s worth it.
I’ve personally struggled to implement a decentralized approach to quality in many of my teams. I believe in it from an academic standpoint, but in practice it works against the grain of every traditional management structure. Managers want ‘one neck to wring’ when things go wrong. Decentralized quality makes that impossible. So I’ve compromised, centralized, become the bottleneck I know slows things down. It’s easier to defend in meetings. But when I’ve managed to decentralize quality — most memorably when I was running a small agency and could write the org chart myself — I’ve been able to do some of the best work of my career.
- Start with the text
- Use size intentionally
- Contrast weights and styles
- Play with spacing
- Use colour, but don’t rely on it
- Limit your font choices (but choose well and wisely)
- Repeat, repeat, repeat
- Test your system
Here’s a comprehensive round-up of new CSS that you can use right now—you can expect to see some of this in action at Web Day Out!
A nifty interactive 3D map of our solar system
Put the kettle on. This is a long one!
Matt takes a trip down memory lane and looks at all the frontend tools, technologies, and techniques that have come and gone over the years.
But this isn’t about nostalgia (although it does make you appreciate how far we’ve come). He’s looking at whether anything from the past is worth keeping today.
Studying past best practices and legacy systems is crucial for understanding the evolution of technology and making informed decisions today.
There’s only one technique that makes the cut:
After discussing countless legacy approaches and techniques best left in the past, you’ve finally arrived at a truly timeless and Incredibly important methodology.
I just found out that Stephanie “Steve” Shirley passed away.
She was an absolute hero to me.