Archive for the 'accessibility web standards' Category

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

Is Apple breaking PWAs out of malicious compliance?

Update 16 Feb: Yes. Apple are indeed breaking PWAs out of malicious compliance.

As the showdown between the European Union and Your Best Friend Apple looms (27 days, according to OWA’s Digital Markets Act Countdown), it appears that Apple is intending to break PWAs in iOS 17.4 beta 2:

Progressive Web Apps (PWAs) are still disabled for EU users in #iOS 17.4 beta 2. But now there’s a new pop-up. The pop-up somehow indicates that PWAs are disabled intentionally, rather than being a bug

Open 'PWA Todayooo' in Safari. 'PWA Todayooo' will open in your default browser from now on.

… It will be a major blow for EU users if iOS 17.4 is released without PWA support. Many major European companies have already converted their native iOS apps into PWAs, mainly to skip the unnecessary overhead imposed by the App Store, such as app distribution and the App Review.

As Thomas Steiner reported “Newly installed apps always open in the browser. There doesn’t appear to be a standalone mode anymore”, thereby robbing PWAs of their central UI feature: the ability to open full-screen and appear identical to a Native app.

Presumably Apple doesn’t want PWAs to open in third-party browsers that have more powerful features than Safari, because those would directly compete with native apps in its own App Store. However, in the EU, it can’t privilege PWAs in Safari with its own private APIs any more. And so its solution, in its spirit of malicious compliance, seems to be “if we can’t have them, nobody can!”. This contradicts Apple’s messaging that web apps are a viable alternative to native:

If the App Store model and guidelines are not best for your app or business idea that’s okay, we provide Safari for a great web experience too.

Has Apple the Good Shepherd turned into a sheepdog in the manger? Perhaps people are reading too much into this; perhaps it’s a bug in the beta – but the appearance of the pop-up message suggests it’s by design.

Whatever it is, it demonstrates the lack of trust in the web development world that Apple even cares about doing the right thing, and only wants to make it as hard as possible for developers and their businesses to take advantage of the new freedoms under the DMA.

I’m no lawyer, but it seems to me that this contravenes the DMA’s anti-circumvention articles:

The gatekeeper shall not degrade the conditions or quality of any of the core platform services provided to business users or end users who avail themselves of the rights or choices laid down in Articles 5, 6 and 7, or make the exercise of those rights or choices unduly difficult, including by offering choices to the end-user in a non-neutral manner, or by subverting end users’ or business users’ autonomy, decision-making, or free choice via the structure, design, function or manner of operation of a user interface or a part thereof.

Let’s see what the EU says.