I think this is quite beautiful—no need to view source; the style sheet is already in the document.
Friday, October 23rd, 2020
Monday, October 19th, 2020
To be blunt, I feel we, the folks who have been involved with designing and developing for the web for a significant period of time–including me as I feel a strong sense of personal responsibility here–are in no small part responsible for it falling far short of its promise.
Sunday, October 18th, 2020
A timeline showing the history of non-digital dataviz.
Friday, October 16th, 2020
Take a look at your smartphone and delete all the apps you don’t really need. For many tasks, you can use a browser on your phone instead of an app.
Privacy-wise, browsers are preferable, because they can’t access as much of your information as an app can.
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.
Tuesday, October 13th, 2020
James made a radio programme about “the cloud”:
It’s the central metaphor of the internet - ethereal and benign, a fluffy icon on screens and smartphones, the digital cloud has become so naturalised in our everyday life we look right through it. But clouds can also obscure and conceal – what is it hiding? Author and technologist James Bridle navigates the history and politics of the cloud, explores the power of its metaphor and guides us back down to earth.
The unfair collusion between Google AMP and Google Search might just bite ‘em on the ass.
Monday, October 12th, 2020
The Web History podcast
Recently Jay started publishing essays on web history over on CSS Tricks:
Round about that time, Chris floated the idea of having people record themselves reading blog posts. I immediately volunteered my services for the web history essays.
So now you can listen to me reading Jay’s words:
Each chapter is round about half an hour long so that’s a solid two hours or so of me yapping.
And if you just can’t get enough of my voice, there’s always the Clearleft podcast …although that’s mostly other people talking, thank goodness.
Saturday, October 3rd, 2020
Every day I’ve been recording myself playing a tune and then posting the videos here on my site.
I’m pretty pleased that I’ve managed to keep up a 200 day streak. I could keep going, but I think I’m going to take a break. I’ll keep recording and posting tunes, but I’m no longer going to give myself the deadline of doing it every single day. I’ll record and post a tune when I feel like it.
It’ll be interesting to see how the frequency changes now. Maybe I’ll still feel like recording a tune most days. Or maybe it’ll become a rare occurrence.
If you want to peruse the 200 tunes recorded so far, you can find them here on my website and in a playlist on YouTube. I also posted some videos to Instagram, but I haven’t been doing that from the start.
I’m quite chuffed with the overall output (even if some of the individual recordings are distinctly sub-par). Recording 200 tunes sounds like a big task by itself, but if you break it down to recording just one tune a day, it becomes so much more manageable. You can stand anything for ten seconds. As I said when I reached the 100 tune mark:
Recording one tune isn’t too much hassle. There are days when it’s frustrating and I have to do multiple takes, but overall it’s not too taxing. But now, when I look at the cumulative result, I’m very happy that I didn’t skip any days.
There was a side effect to recording a short video every day. I created a timeline for my hair. I’ve documented the day-by-day growth of my hair from 200 days ago to today. A self has been inadvertently quantified.
Thursday, October 1st, 2020
I’ll be moderating this online panel next week with Emma Boulton, Holly Habstritt Gaal, Jean Laleuf, and Lola Oyelayo-Pearson.
I’m looking forward to it! Come along if you’re interested in the future of design teams.
What will the near-future look like for design teams? Join us as we explore how processes, team structures and culture might change as our industry matures and grows.
Tuesday, September 29th, 2020
Monday, September 28th, 2020
Sunday, September 27th, 2020
The title says it all, really. This is another great piece of writing from Paul Ford.
I’ve noticed that when software lets nonprogrammers do programmer things, it makes the programmers nervous. Suddenly they stop smiling indulgently and start talking about what “real programming” is. This has been the history of the World Wide Web, for example. Go ahead and tweet “HTML is real programming,” and watch programmers show up in your mentions to go, “As if.” Except when you write a web page in HTML, you are creating a data model that will be interpreted by the browser. This is what programming is.
Tuesday, September 22nd, 2020
You might not think this is a big deal, and maybe it’s not, but I love the idea behind the indie web: a people-focused alternative to the corporate web. Seeing everything you’ve ever linked to in one place really drives home how much of the web’s content, made by individuals, is under corporate control and identity.
Web browsers on iOS
Safari is the only browser on iOS devices.
I don’t mean it’s the only browser that ships with iOS devices. I mean it’s the only browser that can be installed on iOS devices.
You can install something called Chrome. You can install something called Firefox. Those aren’t different web browsers. Under the hood they’re using Safari’s rendering engine. They have to. The app store doesn’t allow other browsers to be listed. The apps called Chrome and Firefox are little more than skinned versions of Safari.
If you’re a web developer, there are two possible reactions to hearing this. One is “Duh! Everyone knows that!”. The other is “What‽ I never knew that!”
If you fall into the first category, I’m guessing you’ve been a web developer for a while. The fact that Safari is the only browser on iOS devices is something you’ve known for years, and something you assume everyone else knows. It’s common knowledge, right?
But if you’re relatively new to web development—heck, if you’ve been doing web development for half a decade—you might fall into the second category. After all, why would anyone tell you that Safari is the only browser on iOS? It’s common knowledge, right?
So that’s the situation. Safari is the only browser that can run on iOS. The obvious follow-on question is: why?
Apple at this point will respond with something about safety and security, which are certainly important priorities. So let me rephrase the question: why on iOS?
Why can I install Chrome or Firefox or Edge on my Macbook running macOS? If there are safety or security reasons for preventing me from installing those browsers on my iOS device, why don’t those same concerns apply to my macOS device?
At one time, the mobile operating system—iOS—was quite different to the desktop operating system—OS X. Over time the gap has narrowed. At this point, the operating systems are converging. That makes sense. An iPhone, an iPad, and a Macbook aren’t all that different apart from the form factor. It makes sense that computing devices from the same company would share an underlying operating system.
As this convergence continues, the browser question is going to have to be decided in one direction or the other. As it is, Apple’s laptops and desktops strongly encourage you to install software from their app store, though it is still possible to install software by other means. Perhaps they’ll decide that their laptops and desktops should only be able to install software from their app store—a decision they could justify with safety and security concerns.
Imagine that situation. You buy a computer. It comes with one web browser pre-installed. You can’t install a different web browser on your computer.
You wouldn’t stand for it! I mean, Microsoft got fined for anti-competitive behaviour when they pre-bundled their web browser with Windows back in the 90s. You could still install other browsers, but just the act of pre-bundling was seen as an abuse of power. Imagine if Windows never allowed you to install Netscape Navigator?
And yet that’s exactly the situation in 2020.
You buy a computing device from Apple. It might be a Macbook. It might be an iPad. It might be an iPhone. But you can only install your choice of web browser on one of those devices. For now.
It is contradictory. It is hypocritical. It is indefensible.
Friday, September 18th, 2020
Don’t blame it on the COBOL:
It’s a common fiction that computing technologies tend to become obsolete in a matter of years or even months, because this sells more units of consumer electronics. But this has never been true when it comes to large-scale computing infrastructure. This misapprehension, and the language’s history of being disdained by an increasingly toxic programming culture, made COBOL an easy scapegoat. But the narrative that COBOL was to blame for recent failures undoes itself: scapegoating COBOL can’t get far when the code is in fact meant to be easy to read and maintain.
It strikes me that the resilience of programmes written in COBOL is like the opposite of today’s modern web stack, where the tangled weeds of nested dependencies ensures that projects get harder and harder to maintain over time.
In a field that has elevated boy geniuses and rockstar coders, obscure hacks and complex black-boxed algorithms, it’s perhaps no wonder that a committee-designed language meant to be easier to learn and use—and which was created by a team that included multiple women in positions of authority—would be held in low esteem. But modern computing has started to become undone, and to undo other parts of our societies, through the field’s high opinion of itself, and through the way that it concentrates power into the hands of programmers who mistake social, political, and economic problems for technical ones, often with disastrous results.
Thursday, September 17th, 2020
They came for the writers of car brochures, but I wasn’t a writer of car brochures, so I said nothing.
Wednesday, September 16th, 2020
A polyfill for button type=”share”
After writing about a declarative Web Share API here yesterday I thought I’d better share the idea (see what I did there?).
I opened an issue on the Github repo for the spec.
The polyfill also demonstrates how feature detection could work. Here’s the code.
This polyfill takes an Inception approach to feature detection. There are three nested levels:
- This browser supports
button type="share". Great! Don’t do anything. Otherwise proceed to level two.
- Use a
mailto:link to prefill an email with the page title as the subject and the URL in the body. Ya basic!
The idea is that, as long as you include the 20 lines of polyfill code, you could start using
button type="share" in your pages today.
I’ve made a test page on Codepen. I’m just using plain text in the button but you could use a nice image or SVG or combination. You can use the Codepen test page to observe two of the three possible behaviours browsers could exhibit:
- A browser supports
button type="share". Currently that’s none because I literally made this shit up yesterday.
- A browser supports neither
The polyfill doesn’t support Internet Explorer 11 or lower because it uses the DOM
closest() method. Feel free to fork and rewrite if you need to support old IE.
This was an absolute delight to read! Usually when you read security-related write-ups, the fun comes from the cleverness of the techniques …but this involved nothing cleverer than dev tools. In this instance, the fun is in the telling of the tale.