Remix and the Alternate Timeline of Web Development - Jim Nielsen’s Blog
It sounds like Remix takes a sensible approach to progressive enhancement.
It sounds like Remix takes a sensible approach to progressive enhancement.
I really like the progressive enhancement approach that this little library uses—it’s basically the Hijax approach I was talking about back in the days of Bulletproof Ajax but all wrapped up into a neat package that you can use entirely via HTML attributes.
I just finished watching The Billion Dollar Code, a German language miniseries on Netflix. It’s no Halt and Catch Fire, but it combines ’90s nostalgia, early web tech, and an opportunity for me to exercise my German comprehension.
It’s based on a true story, but with amalgamated characters. The plot, which centres around the preparation for a court case, inevitably invites comparison to The Social Network, although this time the viewpoint is from that of the underdogs trying to take on the incumbent. The incumbent is Google. The underdogs are ART+COM, artist-hackers who created the technology later used by Google Earth.
Early on, one of the characters says something about creating a one-to-one model of the whole world. That phrase struck me as familiar…
I remember being at the inaugural Future Of Web Apps conference in London back in 2006. Discussing the talks with friends afterwards, we all got a kick out of the speaker from Google, who happened to be German. His content and delivery was like a wonderfully Stranglovesque mad scientist. I’m sure I remember him saying something like “vee made a vun-to-vun model of the vurld.”
His name was Steffen Meschkat. I liveblogged the talk at the time. Turns out he was indeed on the team at ART+COM when they created Terravision, the technology later appropriated by Google (he ended up working at Google, which doesn’t make for as exciting a story as the TV show).
His 2006 talk was all about Ajax, something he was very familiar with, being on the Google Maps team. The Internet Archive even has a copy of the original audio!
It’s easy to forget now just how much hype there was around Ajax back then. It prompted me to write a book about combining Ajax and progressive enhancement.
These days, no one talks about Ajax. But that’s not because the technology went away. Quite the opposite. The technology became so ubiquituous that it no longer even needs a label.
A web developer today might ask “what’s Ajax?” in the same way that a fish might ask “what’s water?”
One of the other arguments we hear in support of the SPA is the reduction in cost of cyber infrastructure. As if pushing that hosting burden onto the client (without their consent, for the most part, but that’s another topic) is somehow saving us on our cloud bills. But that’s ridiculous.
I like this proposal for a declarative Ajax pattern. It’s relatively straightforward to polyfill, although backward-compatibility is an issue because of existing browser behaviour with the target
attribute.
This is great! The folks at Basecamp are releasing the front-end frameworks they use to build Hey. There’s Turbo—the successor to Turbolinks:
It offers a simpler alternative to the prevailing client-side frameworks which put all the logic in the front-end and confine the server side of your app to being little more than a JSON API.
With Turbo, you let the server deliver HTML directly, which means all the logic for checking permissions, interacting directly with your domain model, and everything else that goes into programming an application can happen more or less exclusively within your favorite programming language. You’re no longer mirroring logic on both sides of a JSON divide. All the logic lives on the server, and the browser deals just with the final HTML.
Yes, this is basically Hijax (which is itself simply a name for progressive enhancement applied to Ajax) and I’m totally fine with that. I don’t care what it’s called when the end result is faster, more resilient websites.
Compare and contrast the simplicity of the Hotwire/Turbo approach to the knots that React is tying itself up in to try to get the same performance benefits.
I wrote a little something recently about using ARIA attributes as selectors in CSS. For me, one of the advantages is that because ARIA attributes are generally added via JavaScript, the corresponding CSS rules won’t kick in if something goes wrong with the JavaScript:
Generally, ARIA attributes—like
aria-hidden
—are added by JavaScript at runtime (rather than being hard-coded in the HTML).
But there’s one instance where I actually put the ARIA attribute directly in the HTML that gets sent from the server: aria-live
.
If you’re not familiar with it, aria-live
is extremely useful if you’ve got any dynamic updates on your page—via Ajax, for example. Let’s say you’ve got a bit of your site where filtered results will show up. Slap an aria-live
attribute on there with a value of “polite”:
<div aria-live="polite">
...dynamic content gets inserted here
</div>
You could instead provide a value of “assertive”, but you almost certainly don’t want to do that—it can be quite rude.
Anyway, on the face it, this looks like exactly the kind of ARIA attribute that should be added with JavaScript. After all, if there’s no JavaScript, there’ll be no dynamic updates.
But I picked up a handy lesson from Ire’s excellent post on using aria-live
:
Assistive technology will initially scan the document for instances of the aria-live attribute and keep track of elements that include it. This means that, if we want to notify users of a change within an element, we need to include the attribute in the original markup.
Good to know!
Ten years ago I gave a talk at An Event Apart all about interaction design. It was called Paranormal Interactivity. You can watch the video, listen to the audio or read the transcript if you like.
I think it holds up pretty well. There’s one interaction pattern in particular that I think has stood the test of time. In the talk, I introduce this pattern as something you can see in action on Huffduffer:
I was thinking about how to tell the user that something’s happened without distracting them from their task, and I thought beyond the web. I thought about places that provide feedback mechanisms on screens, and I thought of video games.
So we all know Super Mario, right? And if you think about when you’re collecting coins in Super Mario, it doesn’t stop the game and pop up an alert dialogue and say, “You have just collected ten points, OK, Cancel”, right? It just does it. It does it in the background, but it does provide you with a feedback mechanism.
The feedback you get in Super Mario is about the number of points you’ve just gained. When you collect an item that gives you more points, the number of points you’ve gained appears where the item was …and then drifts upwards as it disappears. It’s unobtrusive enough that it won’t distract you from the gameplay you’re concentrating on but it gives you the reassurance that, yes, you have just gained points.
I think this a neat little feedback mechanism that we can borrow for subtle Ajax interactions on the web. These are actions that don’t change much of the content. The user needs to be able to potentially do lots of these actions on a single page without waiting for feedback every time.
On Huffduffer, for example, you might be looking at a listing of people that you can choose to follow or unfollow. The mechanism for doing that is a button per person. You might potentially be clicking lots of those buttons in quick succession. You want to know that each action has taken effect but you don’t want to be interrupted from your following/unfollowing spree.
You get some feedback in any case: the button changes. Maybe the text updates from “follow” to “unfollow” accompanied by a change in colour (this is what you’ll see on Twitter). The Super Mario style feedback is in addition to that, rather than instead of.
I’ve made a Codepen so you can see a reduced test case of the Super Mario feedback in action.
See the Pen Unobtrusive feedback by Jeremy Keith (@adactio) on CodePen.
Here’s the code available as a gist.
It’s a function that takes two arguments: the element that the feedback originates from (pass in a DOM node reference for this), and the contents of the feedback (this can be a string of text or it can be HTML …or SVG). When you call the function with those two arguments, this is what happens:
span
element and puts the feedback contents inside it.translateY
applied so it drifts upward. At the same time it gets its opacity reduced from 1 to 0 so it’s fading away.transitionend
event that fires when the animation is over. Once that event fires, the generated span
is destroyed.When I first used this pattern on Huffduffer, I’m pretty sure I was using jQuery. A few years later I rewrote it in vanilla JavaScript. That was four years ago so I wonder if the code could be improved. Have a go if you fancy it.
Still, even if the code could benefit from an update, I’m pleased that the underlying pattern still holds true. I used it recently on The Session and it’s working a treat for a new Ajax interaction there (bookmarking or unbookbarking an item).
If you end up using this unobtrusive feedback pattern anyway, please let me know—I’d love to see more examples of it in the wild.
Earlier this year, I wrote about an accessibility issue I was having on The Session. Specifically, it was an issue with Ajax and pagination. But I managed to sort it out, and the lesson was very clear:
As is so often the case, the issue was with me trying to be too clever with ARIA, and the solution was to ease up on adding so many ARIA attributes.
Well, fast forward to the past few weeks, when I was contacted by one of the screen-reader users on The Session. There was, once again, a problem with the Ajax pagination, specifically with VoiceOver on iOS. The first page of results were read out just fine, but subsequent pages were not only never announced, the content was completely unavailable. The first page of results would’ve been included in the initial HTML, but the subsequent pages of results are injected with JavaScript (if JavaScript is available—otherwise it’s regular full-page refreshes all the way).
This pagination pattern shows up all over the site: lists of what’s new, search results, and more. I turned on VoiceOver and I was able to reproduce the problem straight away.
I started pulling apart my JavaScript looking for the problem. Was it something to do with how I was handling focus? I just couldn’t figure it out. And other parts of the site that used Ajax didn’t seem to be having the same problem. I was mystified.
Finally, I tracked down the problem, and it wasn’t in the JavaScript at all.
Wherever the pagination pattern appears, there are “previous” and “next” links, marked up with the appropriate rel="prev"
and rel="next"
attributes. Well, apparently past me thought it would be clever to add some ARIA attributes in there too. My thinking must’ve been something like this:
aria-controls="results"
to those links.That was the problem …which is kind of weird, because VoiceOver isn’t supposed to have any support for aria-controls
. Anyway, once I removed that attribute from the links, everything worked just fine.
Just as the solution last time was to remove the aria-atomic
attribute on the updated area, the solution this time was to remove the aria-controls
attribute on the links that trigger the update. Maybe this time I’ll learn my lesson: don’t mess with ARIA attributes you don’t understand.
Chris looks at all the different ways of working around the fact that HTML doesn’t do transclusion. Those ways include (hah!) Scott’s super clever technique and Trys’s little Sergey.
Hui-Jing talks through her process of building a to-do app on Glitch using a progressive enhancement mindset:
I found that HTML out-of-the-box takes care of a lot of things when it comes to collecting user inputs from the front-end, which resulted in much less code required. This is not to say client-side Javascript is bad, because the experience was smoother (and faster) when I used it for updating content.
I spent some time this weekend working on an accessibility issue over on The Session. Someone using VoiceOver on iOS was having a hard time with some multi-step forms.
These forms have been enhanced with some Ajax to add some motion design: instead of refreshing the whole page, the next form is grabbed from the server while the previous one swooshes off the screen.
You can see similar functionality—without the animation—wherever there’s pagination on the site.
The pagination is using Ajax to enhance regular prev/next links—here’s the code.
The multi-step forms are using Ajax to enhance regular form submissions—here’s the code for that.
Both of those are using a wrapper I wrote for XMLHttpRequest.
That wrapper also adds some ARIA attributes. The region of the page that will be updated gets an aria-live
value of polite
. Then, whenever new content is being injected, the same region gets an aria-busy
value of true
. Once the update is done, the aria-busy
value gets changed back to false
.
That all seems to work fine, but I was also giving the same region of the page an aria-atomic
value of true
. My thinking was that, because the whole region was going to be updated with new content from the server, it was safe to treat it as one self-contained unit. But it looks like this is what was causing the problem, especially when I was also adding and removing class
values on the region in order to trigger animations. VoiceOver seemed to be getting a bit confused and overly verbose.
I’ve removed the aria-atomic
attribute now. True to its name, I’m guessing it’s better suited to small areas of a document rather than big chunks. (If anyone has a good primer on when to use and when to avoid aria-atomic
, I’m all ears).
I was glad I was able to find a fix—hopefully one that doesn’t negatively impact the experience in other screen readers. As is so often the case, the issue was with me trying to be too clever with ARIA, and the solution was to ease up on adding so many ARIA attributes.
It also led to a nice discussion with some of the screen-reader users on The Session.
For me, all of this really highlights the beauty of the web, when everyone is able to contribute to a community like The Session, regardless of what kind of software they may be using. In the tunes section, that’s really helped by the use of ABC notation, as I wrote five years ago:
One of those screen-reader users got in touch with me shortly after joining to ask me to explain what ABC was all about. I pointed them at some explanatory links. Once the format “clicked” with them, they got quite enthused. They pointed out that if the sheet music were only available as an image, it would mean very little to them. But by providing the ABC notation alongside the sheet music, they could read the music note-for-note.
That’s when it struck me that ABC notation is effectively alt text for sheet music!
Then, for those of use who can read sheet music, the text of the ABC notation is automatically turned into an SVG image using the brilliant abcjs. It’s like an enhancement that’s applied, I dunno, what’s the word …progressively.
A terrific explanation of the aria-live
attribute from Ire. If you’re doing anything with Ajax, this is vital knowledge.
A thorough explanation of the history and inner workings of Cross-Origin Resource Sharing.
Like tales of a mythical sea beast, every developer has a story to tell about the day CORS seized upon one of their web requests, dragging it down into the inexorable depths, never to be seen again.
This looks like a handy library for managing page transitions on sites that are not single page apps.
I’ve said it before and I’ll say it again, but I really think that this handles 80% of the justification for using a single page app architecture.
This is a really good use-case for cancelling fetch requests: making API calls while autocompleting in search.
This is definitely the best review of any of my books.
Google may or may not decide to run your JavaScript, and you don’t want your business to depend on its particular inclination of the day. Do server-side/universal/isomorphic rendering just to be safe.
I saw Christian speak on this topic at Smashing Conference in Barcelona. Here, he takes a long hard look at some of the little things that sites get wrong when doing validating forms on the fly. It’s all good sensible stuff, although it sounds a bit medical when he takes about “Premature Inline Validation.”
This is a truly fantastic example of progressive enhancement applied to a form.
What I love about this is that it shows how progressive enhancement isn’t a binary on/off choice: there are layers and layers of enhancements here, from simple inline validation all the way to service workers and background sync, with many options in between.
Superb!