Bruce Lawson's personal site

Book review: Prophet’s Song by Paul Lynch

I mostly enjoyed this Booker-winning novel about a family in Ireland suffering under an increasingly authoritarian government, as the country swiftly descends into civil war. The politics aren’t fleshed out; it’s about the psychological effects of civil war and being a minority (in this case, the husband is a “disappeared” Trade Union leader). It’s very much a book of our time; this isn’t set in the “day after tomorrow”; it’s today. Apart from the street names and the Irish-accented dialogue, it could be set in Damascus or Darfur.

But what put me off what the author’s stylistic decision to avoid paragraphs or quotation marks. Much of the book was two pages of solid text, justified left and right so it was not at all easy on the eye. Here’s a photo of a random but representative spread:

A photo of a two pages from the  book

The lack of speech marks meant that often I couldn’t tell when one person’s reported speech ended and another participant in a conversation began, or when narration recommenced. For example, from the randomly chosen spread from the photo:

Carole looks up as the waitress steps towards them with a tray and places the drinks on the table then smiles and steps quickly away. You look as though you haven’t slept in a week, Eilish says, are you sleeping at all? Sleep, Carole says, her voice distant, far off in time, she looks across the table at Eilish without seeing her. I don’t sleep much at all, she says

(There were more egregious examples, but I left the book in my hotel room when I finished my holiday, as I knew I wouldn’t want to re-read it.)

The effect of this is that I would lose the thread and have to re-read to parse and make sense of the dialogue, and the monolithic slab of text made it difficult to find the place to re-read from. This was annoying, and got in the way of the excitement of the story.

I think this would be a great film or Netflix mini-series. Unfortunately, Lynch’s too-cool-for-punctuation prose got in the way of the narrative.

CSS :has(), the God Selector

Probably everybody knows this, but I didn’t and in case you don’t, here’s why the CSS :has() pseudo-class is omnipotent and so awe-inspiring I call it the God Selector.

I was working on a no-JavaScript fallback for a mobile hamburger menu, using the newly-baseline HTML Popover API. For users without JavaScript (and, yes, there are many), the code looks like this:

<header>
<a><picture> <!-- Logo homelink --> </picture></a>
<button> <!-- big fat CTA --> </button>
<search> .. </search>
<button popovertarget="narrowscreen-nav">Menu</button>
<nav id="narrowscreen-nav" popover> ... </nav>
</header>

I wanted to give the button a different style if its associated popover is shown. There is no pseudo-class for button:pressed (which is why some people like the checkbox hack, which is clever but has the wrong semantics. And, anyway, popovers can’t be triggered from inputs).

There is, however, a pseudo-class to tell you if a popover is open: :popover-open. Now, to find a way to style the button element by targetting this aspect of its associated (but not descendant) popover target element.

Sometimes people called :has a “parent selector”, but it’s not only that. I knew that it could “reach out” and look at siblings etc if there is the necessary CSS combinator. This selector worked for my code:

button:has(~nav:popover-open) {background-color: goldenrod;}

However, I wasn’t happy about it; what happens if the nav ceases to be a sibling (as it soon did, because I needed a wrapper around the stuff before the nav, to lay it out using Flexbox)? I tend to dislike handing code over to clients that has a very tight dependancy on exact markup structure.

Luckily, I had a conversation with the splendid Luke Warlow of Igalia (a free software consultancy/ hippie commune who do loads of work in all the browser engines), and he blew my mind. It turns out I was thinking about :has the wrong way round.

Behold the almighty God Selector:

:has(nav:popover-open) button[popovertarget] {background-colour:goldenrod;}

This is omnipotent because it doesn’t require any structural relationship between the thing being checked and the thing being styled. The first bit of the selector :has(nav:popover-open} doesn’t have a class, ID or element name, so is scoped to the root of the document. That’s the thing being checked: is there a nav that is an open popover anywhere in this page?

The second part of the selector is the thing to be styled, which is a descendant of the root – and, of course, everything on the page is a descendant of the html element, which is the root. Think of the selector as html:has(nav:popover-open) button[popovertarget] if that makes it easier to reason about.

Of course, you can narrow it down to hone in on the exact nav or button you’re interested in. For example,

header:has(nav:popover-open} button.letsBeSpecific[popovertarget] {background-color:goldenrod;}

And now, I’ve used the God Selector in three different places in the same stylesheet already, to achieve an effect I could not have done without handing over markup of much greater fragility. Thank you to the Mighty Luke Warlow, and I’ll have a kilo of whatever goes in the Igalia bong.

Reading List 318

Reading List 317

Reading List 316

Drive-by accessibility tweaks

Sometimes, if I’m fixing an unrelated bug I spot the opportunity to make a quick “drive-by” accessibility tweak that is quick and easy and will give a disproportionately big boost to the user experience for people with accessibility needs.

Here are some of my top faves (number 3 will have you in tears!). Your mileage may vary, of course, depending on your codebase and conventions.

Replace meaningless divs with landmark semantics

In some codebases, I see lots of HTML festooned with classes, which are used to style the element rather than apply styles to the element directly, so <div class="header"> and a CSS rule .header {display:block; color: goldernrod; …} instead of header {color: goldernrod; …} as Sir Uncle Timbo intended.

This allows me to change it to <header class="header"> with no need to rewrite the CSS, and assistive technology users get information and navigation assistance from the semantic of header (whereas div is meaningless).

If your codebase is similarly styled, you can do this with nav, main, footer too; my article The practical value of semantic HTML explains the benefits.

I often add a <search> element too, if the JS/ ARIA labyrinth isn’t too deep.

Make in-page links more accessible

Another sneaky quick win involves adding tabindex=”-1″ to the target of in-page links, so focus isn’t lost after the link is followed.

So if you have <a href="#mainContent">Skip to main content</a> in your page (and if you haven’t, why not??) the target of that link needs a tabindex:

<main id="mainContent" tabindex="-1">

I had thought this problem had gone away when Internet Explorer was laid to rest, but no.

Replace JS accordions with HTML

Depending on your codebase, this may not be as easy. But there are literally 735 trillion sites (and crusty old libraries and creaky tutorials ) that still use cobwebby JavaScript to make accordions and similar disclosure widgets, with fragile ARIA and focus management.

For years, HTML <details> and <summary> just do it for you, managing roles and states for free without any JavaScript, and they work everywhere. You might have to get more creative if you need an animated arrow (can you imagine the shame of a disclosure widget without an animation?!?) but it can be done.

You can also consider replacing your Penny Farthing JavaScript dialog boxes and popovers with HTML <dialog> which works everywhere and (soon) the HTML popover attribute and associated API, and get all your focus management, roles and states and z-index shenanigans handled by the browser for free.

Remember, kids: built-in beats bolt-on. Bigly. Happy drive-by accessibility tweaking!

Apple’s new Core Technology Fee is a Core Technology Fleece

At the recent EU-organised workshop, Apple explained its proposals for its compliance with the Digital Markets Act, and took questions from developers. One developer, Riley Testut of AltStore (which has announced it will be a third-party app store in the EU) asked an interesting question about Apple’s new Core Technology Fee. He noted that the free open-source app he made and released while at High School would have put him in 5 million Euros of debt to Apple under their new fee structure, even though it was not distributed through its AppStore.

Apple’s lawyer made soothing noises about Apple wanting to support “the dreamers” and to “stay tuned”, presumably for any exceptions Apple may graciously bestow on such developers.

But it made me wonder: what is the Core Technology Fee actually for, if a developer makes an app and distributes it outside the AppStore? So, I asked:

A developer who wants to make an iOS app must do it on a Mac; these are not cheap, and only available from Apple. You’ll need an iPhone to test it (the xcode simulator won’t allow you to check accessibility with Voiceover). You’ll probably want an iPad, too – bafflingly, apps can work on iPads too, even though iOS and iPadOS are completely different operating systems (according to Apple).

A developer license costs $99 per year (although it’s unclear to me if you actually need one if you’re not uploading your app to the AppStore). And if a consumer wants to download your app, they will need a shiny iThing, which they’ve bought from Apple at a premium price, precisely to reimburse Apple for the core technology it contains. Would anyone buy an iPhone if there were no apps available?

So I don’t buy Apple’s argument that developers must pay them for the core technology that the iPhone user has already paid them for. And I wonder if the EU believe it, either; EU antitrust chief Margrethe Vestager said after the workshop

There are things that we take a keen interest in, for instance, if the new Apple fee structure will de facto not make it in any way attractive to use the benefits of the DMA. That kind of thing is what we will be investigating.

To quote Apple’s legal team: stay tuned.

Reading List 315

Happy DMA day to all! Where we are, and what comes next

Yesterday was a momentous day for tech in the European Union; the Digital Markets Act came into enforcement on 7 March. It’s been the law for 6 months already, but affected companies (Apple, Google, Microsoft, Meta, the usual colossi) were given a grace period to prepare themselves.

Apple spent their time playing silly buggers. They hilariously tried to claim that Safari is a different product on each OS, successfully (but ridiculously) claimed that iOS on tablets is different from iOS on phones.

Then they tried to sneak in a change in Safari that crippled Progressive Web Apps (aka Home Screen Apps) on iOS, presumably concluding that if they hobbled their own browser before the enforcement began, they wouldn’t be on the hook for denying those capabilities to other browser engines they’re required to allow.

Yup, that’s right; they were prepared to throw their own WebKit and Safari teams under the bus and remove Web Push, the Badging API, and all the other work those teams had done. They were happy to destroy many EU businesses that relied on PWAs, and harm those users. They were fine with sneaking in anti-competitive behaviour while blaming the very legislation that is designed to open competition.

As the Financial Times reported, ‘”Contrary to Apple’s public representation, the removal of Home Screen Web Apps on iOS in the EU was neither required, nor justified, under the Digital Markets Act,” a commission spokesperson added.’

Luckily, we managed to organise an open letter to Apple CEO Tim Cook, which was signed by 483 organisations and 4640 individuals (including two Members of the European Parliament), the EU swiftly started investigating, and Apple backed off. To all those who signed: know that your voices were heard, loudly, in Brussels and Cupertino and you made a difference. Thank you.

So where are we now? Apple has revised its statement on killing Web Apps, saying instead

We have received requests to continue to offer support for Home Screen web apps in iOS, therefore we will continue to offer the existing Home Screen web apps capability in the EU. This support means Home Screen web apps continue to be built directly on WebKit and its security architecture, and align with the security and privacy model for native apps on iOS.

This is not a victory; Apple says iOS will still only be able to run Web Apps on the WebKit that it provides, with all its bugs and restrictions.

But a stated compliance plan from an organisation that only four days ago was fined over €1.8 billion for restricting competition in Music apps is not necessarily what everyone else agrees to be compliance. And the EU has already experienced Apple’s complex relationship with ‘facts’ and ‘truth’:

In setting the level of the fine, the Commission took into account the duration and gravity of the infringement as well as Apple’s total turnover and market capitalization. It also factored in that Apple submitted incorrect information in the framework of the administrative procedure.

So I’d be willing to bet that the EU is not okay with Apple’s PWA WebKit restriction. Apple imposes WebKit as the engine for PWAs, yet Recital 43 of the DMA is clear:

When gatekeepers operate and impose web browser engines, they are in a position to determine the functionality and standards that will apply not only to their own web browsers, but also to competing web browsers and, in turn, to web software applications.

An apple with a halloween face, and the acronym 'iANAL'

I am not a lawyer, merely a Lawson. But I’d also be willing to bet that Apple’s proposed deeply onerous terms for third party browsers are anti-competitive too.

On Monday 18 March, the EU is holding an Apple DMA compliance workshop

to provide interested parties with the possibility to ask for clarifications and to give feedback on the proposed compliance solutions.

It will be interesting to see whether EU developers and businesses believe Apple is fully complying with the Digital Markets Act’s intention and requirements. As Commissioner for Internal Market of the European Union, Thierry Breton, tweeted

🚨Under the #DMA, there is no room for threats by gatekeepers to silence developers… To all developers in 🇪🇺 & 🌍: now is the time to have your say on gatekeepers’ compliance solutions!

Mr Breton told Reuters:

The DMA will open the gates of the internet to competition so that digital markets are fair and open. Change is already happening. As from March 7 we will assess companies’ proposals, with the feedback of third parties. If the proposed solutions are not good enough, we will not hesitate to take strong action.

Under the DMA, the Commission can impose fines up to 10% of the company’s total worldwide turnover, which can go up to 20% in case of repeated infringement.

Read more

Reading List 314