Increasingly, I think UX doesn’t live up to its original meaning of “user experience.” Instead, much of the discpline today, as it’s practiced in Big Tech firms, is better described by a new name.
UX is now “user exploitation.”
Friday, February 12th, 2021
Wednesday, February 3rd, 2021
Two-factor authentication is generally considered A Good Thing™️ when you’re logging in to some online service.
The word “factor” here basically means “kind” so you’re doing two kinds of authentication. Typical factors are:
- Something you know (like a password),
- Something you have (like a phone or a USB key),
- Something you are (biometric Black Mirror shit).
Asking for a password and an email address isn’t two-factor authentication. They’re two pieces of identification, but they’re the same kind (something you know). Same goes for supplying your fingerprint and your face: two pieces of information, but of the same kind (something you are).
None of these kinds of authentication are foolproof. All of them can change. All of them can be spoofed. But when you combine factors, it gets a lot harder for an attacker to breach both kinds of authentication.
The most common kind of authentication on the web is password-based (something you know). When a second factor is added, it’s often connected to your phone (something you have).
Every security bod I’ve talked to recommends using an authenticator app for this if that option is available. Otherwise there’s SMS—short message service, or text message to most folks—but SMS has a weakness. Because it’s tied to a phone number, technically you’re only proving that you have access to a SIM (subscriber identity module), not a specific phone. In the US in particular, it’s all too easy for an attacker to use social engineering to get a number transferred to a different SIM card.
Still, authenticating with SMS is an option as a second factor of authentication. When you first sign up to a service, as well as providing the first-factor details (a password and a username or email address), you also verify your phone number. Then when you subsequently attempt to log in, you input your password and on the next screen you’re told to input a string that’s been sent by text message to your phone number (I say “string” but it’s usually a string of numbers).
There’s an inevitable friction for the user here. But then, there’s a fundamental tension between security and user experience.
In the world of security, vigilance is the watchword. Users need to be aware of their surroundings. Is this web page being served from the right domain? Is this email coming from the right address? Friction is an ally.
But in the world of user experience, the opposite is true. “Don’t make me think” is the rallying cry. Friction is an enemy.
With SMS authentication, the user has to manually copy the numbers from the text message (received in a messaging app) into a form on a website (in a different app—a web browser). But if the messaging app and the browser are on the same device, it’s possible to improve the user experience without sacrificing security.
If you’re building a form that accepts a passcode sent via SMS, you can use the
autocomplete attribute with a value of “one-time-code”. For a six-digit passcode, your
input element might look something like this:
<input type="text" maxlength="6" inputmode="numeric" autocomplete="one-time-code">
With one small addition to one HTML element, you’ve saved users some tedious drudgery.
There’s one more thing you can do to improve security, but it’s not something you add to the HTML. It’s something you add to the text message itself.
Let’s say your website is example.com and the text message you send reads:
Your one-time passcode is 123456.
Add this to the end of the text message:
So the full message reads:
Your one-time passcode is 123456. @example.com #123456
The first line is for humans. The second line is for machines. Using the @ symbol, you’re telling the device to only pre-fill the passcode for URLs on the domain example.com. Using the # symbol, you’re telling the device the value of the passcode. Combine this with
autocomplete="one-time-code" in your form and the user shouldn’t have to lift a finger.
I’m fascinated by these kind of emergent conventions in text messages. Remember that the @ symbol and # symbol in Twitter messages weren’t ideas from Twitter—they were conventions that users started and the service then adopted.
You can add a URL for
/.well-known/change-password which redirects to the form a user would use to update their password. Browsers and password managers can then use this information if they need to prompt a user to update their password after a breach. I’ve added this to The Session.
Oh, and on that page where users can update their password, the
autocomplete attribute is your friend again:
<input type="password" autocomplete="new-password">
If you want them to enter their current password first, use this:
<input type="password" autocomplete="current-password">
All of the things I’ve mentioned—the
autocomplete attribute, origin-bound one-time codes in text messages, and a well-known URL for changing passwords—have good browser support. But even if they were only supported in one browser, they’d still be worth adding. These additions do absolutely no harm to browsers that don’t yet support them. That’s progressive enhancement.
Monday, November 16th, 2020
Goodhart’s Law applied to Google’s core web vitals:
If developers start to focus solely on Core Web Vitals because it is important for SEO, then some folks will undoubtedly try to game the system.
Personally, my beef with core web vitals is that they introduce even more uneccessary initialisms (see, for example, Harry’s recent post where he uses CWV metrics like LCP, FID, and CLS—alongside TTFB and SI—to look at PLPs, PDPs, and SRPs. I mean, WTF?).
Wednesday, October 14th, 2020
I added a long-overdue enhancement to The Session recently. Here’s the scenario…
You’re on a web page with a comment form. You type your well-considered thoughts into a
textarea field. But then something happens. Maybe you accidentally navigate away from the page or maybe your network connection goes down right when you try to submit the form.
This is a textbook case for storing data locally on the user’s device …at least until it has safely been transmitted to the server. So that’s what I set about doing.
My first decision was choosing how to store the data locally. There are multiple APIs available:
localStorage. It was clear that
sessionStorage wasn’t right for this particular use case: I needed the data to be saved across browser sessions. So it was down to
IndexedDB is the more versatile and powerful—because it’s asynchronous—but
localStorage is nice and straightforward so I decided on that. I’m not sure if that was the right decision though.
Alright, so I’m going to store the contents of a form in
localStorage. It accepts key/value pairs. I’ll make the key the current URL. The value will be the contents of that
textarea. I can store other form fields too. Even though
localStorage technically only stores one value, that value can be a JSON object so in reality you can store multiple values with one key (just remember to parse the JSON when you retrieve it).
Now I know what I’m going to store (the
textarea contents) and how I’m going to store it (
localStorage). The next question is when should I do it?
I could play it safe and store the comment whenever the user presses a key within the
textarea. But that seems like overkill. It would be more efficient to only save when the user leaves the current page for any reason.
Alright then, I’ll use the
unload event. No! Bad Jeremy! If I use that then the browser can’t reliably add the current page to the cache it uses for faster back-forwards navigations. The page life cycle is complicated.
In either case, just adding a listener for the event could screw up the caching of the page for back-forwards navigations. I should only listen for the event if I know that I need to store the contents of the
textarea. And in order to know if the user has interacted with the
textarea, I’m back to listening for key presses again.
But wait a minute! I don’t have to listen for every key press. If the user has typed anything, that’s enough for me. I only need to listen for the first key press in the
addEventListener accepts an object of options. One of those options is called “
once”. If I set that to
true, then the event listener is only fired once.
So I set up a cascade of event listeners. If the user types anything into the
textarea, that fires an event listener (just once) that then adds the event listener for when the page is unloaded—and that’s when the
textarea contents are put into
I’ve abstracted my code into a gist. Here’s what it does:
- Cut the mustard. If this browser doesn’t support
localStorage, bail out.
- Set the
localStoragekey to be the current URL.
- If there’s already an entry for the current URL, update the
textareawith the value in
- Write a function to store the contents of the
localStoragebut don’t call the function yet.
- The first time that a key is pressed inside the
textarea, start listening for the page being unloaded.
- When the page is being unloaded, invoke that function that stores the contents of the
- When the form is submitted, remove the entry in
localStoragefor the current URL.
That last step isn’t something I’m doing on The Session. Instead I’m relying on getting something back from the server to indicate that the form was successfully submitted. If you can do something like that, I’d recommend that instead of listening to the form submission event. After all, something could still go wrong between the form being submitted and the data being received by the server.
Still, this bit of code is better than nothing. Remember, it’s intended as an enhancement. You should be able to drop it into any project and improve the user experience a little bit. Ideally, no one will ever notice it’s there—it’s the kind of enhancement that only kicks in when something goes wrong. A little smidgen of resilient web design. A defensive enhancement.
Saturday, September 19th, 2020
Thursday, September 17th, 2020
This is a terrific collection of guidelines for form design.
Monday, September 14th, 2020
A short web book on the past, present and future of interfaces, written in a snappy, chatty style.
From oral communication and storytelling 500,000 years ago to virtual reality today, the purpose of information interfaces has always been to communicate more quickly, more deeply, to foster relationships, to explore, to measure, to learn, to build knowledge, to entertain, and to create.
We interface precisely because we are human. Because we are intelligent, because we are social, because we are inquisitive and creative.
We design our interfaces and they in turn redefine what it means to be human.
Friday, August 28th, 2020
The removal of all friction should’t be a goal. Making things easy and making things hard should be a design tool, employed to aid the end user towards their loftiest goals.
Thursday, August 13th, 2020
Back in February, I wrote about an excellent proposal by Jake for how browsers could display URLs in a safer way. Crucially, this involved highlighting the important part of the URL, but didn’t involve hiding any part. It’s a really elegant solution.
Turns out it was a Trojan horse. Chrome are now running an experiment where they will do the exact opposite: they will hide parts of the URL instead of highlighting the important part.
You can change this behaviour if you’re in the less than 1% of people who ever change default settings in browsers.
I’m really disappointed to see that Jake’s proposal isn’t going to be implemented. It was a much, much better solution.
No doubt I will hear rejoinders that the “solution” that Chrome is experimenting with is pretty similar to what Jake proposed. Nothing could be further from the truth. Jake’s solution empowered users with knowledge without taking anything away. What Chrome will be doing is the opposite of that, infantalising users and making decisions for them “for their own good.”
Seeing a complete URL is going to become a power-user feature, like View Source or user style sheets.
I’m really sad about that because, as Jake’s proposal demonstrates, it doesn’t have to be that way.
Sunday, August 9th, 2020
I guess, because browser-makers tend to be engineers so they do engineering-type things like making the browser an app-delivery platform able to run compiled code. Or fight meaningless user experience battles like hiding the URL, or hiding View Source – both acts that don’t really help early users that much, but definitely impede the user path from being a consumer to being a fully-fledged participant/maker.
Saturday, August 1st, 2020
So, why would you want to use a service worker? Here are some cool things you can do with it.
Chris lists some of the ways a service worker can enhance user experience.
The evolution of affordances on the web:
The URL for a page goes at the top. Text appears in a vertically scrolling column. A dropdown menu has a downward-pointing triangle next to it. Your mouse cursor is a slanted triangle with a tail, and when you hover over a link it looks like Mickey Mouse’s glove.
Most of these affordances don’t have any relationship to the physical characteristics of the interaction they mediate. But remove them from a website, application, or interface, and users get disoriented, frustrated, and unproductive.
Monday, July 27th, 2020
This is an interesting project to try to rank web hosts by performance:
Real-world server response (Time to First Byte) latencies, as experienced by real-world users navigating the web.
Thursday, July 23rd, 2020
4 Design Patterns That Violate “Back” Button Expectations – 59% of Sites Get It Wrong - Articles - Baymard Institute
Some interesting research in here around user expecations with the back button:
Generally, we’ve observed that if a new view is sufficiently different visually, or if a new view conceptually feels like a new page, it will be perceived as one — regardless of whether it technically is a new page or not. This has consequences for how a site should handle common product-finding and -exploration elements like overlays, filtering, and sorting. For example, if users click a link and 70% of the view changes to something new, most will perceive this to be a new page, even if it’s technically still the same page, just with a new view loaded in.
Monday, July 20th, 2020
Thoughts on user experience design and service design, prompted by the Clearleft podcast:
I especially enjoyed the latest episode about a topic that has become a bit of a hyped buzzword over the last few years: Service design.
Rich with anecdotes and stories, the episode started with an investigation: What is service design, anyway?
Wednesday, July 15th, 2020
Service design on the Clearleft podcast
If you’re subscribed to the Clearleft podcast there’s a new episode winging its way across the airwaves to alight in your podcast software of choice.
This episode is all about service design. More precisely, it’s about me trying to understand what service design is. I don’t think I’m alone in being unsure of its meaning.
So in some ways, this is similar to the first episode, which involved a lot me asking “What exactly is a design system anyway?” But for the service design episode, rather than using interviews as my source material, I’ve dug into the archives of UX London. There are past talks on Clearleft’s Vimeo channel. I made plenty of use of presentations by Kerry Bodine, Jamin Hegeman, and Lou Downe.
That worked out well, but I felt there was still something missing from the episode. It needed a good story to wrap things up. So I cornered Rich for a chat about a project Clearleft worked on for Brighton council. That did the trick!
Again, there’s not much of me in this one. I’m there to thread the narrative together but my voice is not the one doing the explaining or the story-telling.
The episode ended up being almost half an hour long. Like I said before, rather than trying to squeeze each episode into a predefined timeslot, each episode will be as long as needs to be. And this one needed the time for Rich to tell his story.
Ooh, and I even tried adding in some sound effects during that part! It probably just sounds cheesy, but I’m still trying to figure out what works and what doesn’t.
Anyway, have a listen to this episode and see what you think. It’s got dead badgers, Downton Abbey, icebergs, and airplanes. Service design really does encompass a lot!
Wednesday, June 10th, 2020
Smart thinking from Sara to improve usability for keyboard users by using
aria-hidden="true" tabindex="-1" to skip duplicate links:
A good rule of thumb for similar cases is that if you have multiple consecutive links to the same page, there is probably a chance to improve keyboard navigation by skipping some of those links to reduce the number of tab stops to one. The less tab stops, the better, as long as it does not worsen or compromise on other aspects of usability.
I’ve cautiously implemented this pattern now over on The Session where snippets of comments had both a title link and a “more” link going to the same destination.
Sunday, May 31st, 2020
Tuesday, May 12th, 2020
Spot-on description of “modern” web development. When did this become tolerable, much less normal?
Web developers: maybe stop insisting that your users compile your apps for you? Or admit that you’ll put them through an experience that you certainly don’t tolerate on your own desktops, where you expect to download an app, not to be forced to compile it every time you run it?
Some good thought morsels from Robin on product design:
Bad product design is when folks talk more about the UI than what the UI is built on top of.
There’s a lot of talk about how great design is invisible—mostly boring conversations with little substance—but! I think that’s true when it comes to product design.
Bad product design is when your interface looks like your org chart.