Web Share API meets A11Y


Once every blue moon a JavaScript-related article ends up on this site. Today is such a moon. Let me set the scene for you.

As part of my recent Twitter shutdown, I upgraded my site by replacing tweet intents with the Web Share API.

Jeremy Keith wrote about the Web Share API when he added it to thesession.org. I’ve been able to reuse his code verbatim:

	title: document.querySelector('title').textContent,
	text: document.querySelector('meta[name="description"]').getAttribute('content'),
	url: document.querySelector('link[rel="canonical"]').getAttribute('href')

This is all you need to get rich sharing functionality. Neat. However, this only works in browsers that support the Web Share API. What else do we need beforehand?

By looking at The Session, I noticed Jeremy utilises a button labeled “Share”, which opens a popover. When opened, you find another button that allows you to copy the URL of the current page, and two links with different protocols: “mailto” and “sms”. Both allow you to share the current page, either via e-mail or text message. In browsers that support the Web Share API, the “Share” button no longer opens the popover, but instead calls navigator.share.

I on the other hand wanted to keep it more basic, so I put a single mailto link directly on the page. I prepopulate the title as subject and the link as the body of the message, just like Jeremy did with the mailto link in his popover.

const title = document.querySelector('title').textContent;
const url = document.querySelector('link[rel="canonical"]').getAttribute('href');

const link = `<a href="mailto:?subject=${url}&body=${title}">Share this page</a>`;

In browers that support the Web Share API, I’ll hijack the link and prevent it’s default event. This way, things even work for those who browse the web without JavaScript. Sure enough, it’s 2024, so I could recreate Jeremy’s solution with a native popover, which in its most simple form also works without JavaScript. But that’s a topic for another blog post.

Alright. I’ve progressively enhanced the already present link. But! What I *should* have done is something akin to what Phil Nash’s web-share-wrapper web component does, namely replacing the link with a button on the fly, because calling navigator.share does something (button), it does not go anywhere (link). My inner accessibility advocate agrees, so why did I still choose to *not* do that?

Well, the link has additional value. Unlike a button, a link gives you a context menu on right-click. How browsers behave when you right-click a mailto link varies. I’ve noticed Firefox removes all “Open in new …” entries that you get with a regular link. Which is unnecessary—and half-assed—, because holding the Shift key while you right-click does bring back “Open in new tab” anyway.

But why would you open a mailto link in a new tab? I’m glad I asked. Doing so gives us the option to bypass the progressive enhancement, i.e. the link behaves as if it was never hijacked in the first place. Voilà, back to mailto instead of navigator.share(). Granted, only power users may be aware of that, but still.

So my conundrum is: Do I choose a tiny bit of additional functionality, or semantic correctness?

As said, currently I’m doing the former, but I might give it another thought for accessibility reasons. What do you think? My implementation is already live, there’s a “Share” link below the comments. You can also check it out in more detail on CodePen.