DEV Community

loading...
Cover image for Native "tap to share" in JavaScript with the Web Share API: Current status, tips, and limitations.
Grafton Studio

Native "tap to share" in JavaScript with the Web Share API: Current status, tips, and limitations.

Matteo Cargnelutti
CTO & Software Developer at Grafton Studio, Boston MA. Interested in everything Web standards, Python, Javascript. He/Him, πŸ‡ΊπŸ‡ΈπŸ‡«πŸ‡·.
・Updated on ・4 min read

"This specification (Web Share API) defines an API for sharing text, links and other content to an arbitrary destination of the user's choice."

While the official Web Share API definition does not sound too exciting, this new feature actually offers a solution to a problem web developers have been facing for a decade.
This new API provides a way of using the native "share" feature of the browser or operating system via JavaScript, allowing users to seamlessly share a piece of content from the browser the same way they would from a native application.

No more need for (often) bloated and (sometimes) nosey third-party share "plugins" and their endless lists of social media icons? Well, we are not quite there yet, but let's see how we can already use this new Web API to our advantage.


How does it work?

This API consists in two methods that were added to the navigator object, share() and canShare(). Both receive a ShareData dictionary, containing information to share from the current page to another service, picked by the user from their installed apps list.

It is important to note that, because they are sensitive by nature, none of these methods can be used on a non-HTTPS web page. While implementations may vary, this aspect is part of the specification.

Sharing

The nature of the dictionary that navigator.share() uses, called ShareData, is pre-defined as to ensure interoperability, and looks as follow:

const toShare = {
  title: "@macargnelutti on dev.to",
  text: "Have a look at my posts on dev.to!",
  url: "https://dev.to/macargnelutti/"
};
Enter fullscreen mode Exit fullscreen mode

The ShareData object - in theory - cannot hold anything besides title, text and url. However, the current specification does not suggest a limited length for text, and it is therefore likely possible to pass stringified JSON or base64-encoded content to it. Whether it's a good idea or not is a whole other debate (Spoiler alert: it's probably not).

navigator.share, which takes this dictionary as a parameter, returns a Promise that will be pending while the user makes their choice.

const button = document.querySelector('button');
button.addEventListener('click', async () => {
  try {
    await navigator.share(toShare); // Will trigger the native "share" feature
    button.textContent = 'Shared !';
  }
  catch(err) {
    button.textContent = 'Something went wrong'; 
    console.log(err);
  }
});
Enter fullscreen mode Exit fullscreen mode

The Web Share API at work on mobile and desktop

Interestingly, it appears to be possible to distinguish an exception that arose because the share feature failed or because the user cancelled the action: Safari currently raises an AbortError upon cancellation.

Safari raises an AbortError exception upon cancelation of navigator.share

In addition, part of the early Web Share API Level 2 specification draft, the navigator.canShare method allows to make sure a ShareData dictionary is suitable for sharing before making a request.

This comes in handy to navigate between implementations of the Web Share API: for example, Google's current implementation of the API allows for sharing files via a files attribute, which is part of the latest Community Draft for Web Share API level 2 but not of the latest Web Share API level 1 Working Draft, as mentioned earlier.

Using canShare makes a lot of sense in that context.

const toShare = {
  title: "Viruses in a trench coat",
  text: "Definitely not 5 viruses in a trench coat",
  files: [...]
}

if (navigator.canShare(toShare)) {
  console.log('We can use the Web Share API to share this.');
}
Enter fullscreen mode Exit fullscreen mode

Receiving shared data in your PWA

Through the very experimental Web Share Target API, it is possible to build progressive web apps able to receive that type of information simply by using manifest.json, which makes the Web Share API all the more powerful.

I recommend Google's Web.dev guide on the topic.


Current status and limitations

While in the works since 2016 and still experimental, the standardization process of that feature seems to be making good progress, with a first public working draft released last December.

Current support for navigator.share makes it more than usable on mobile, with iOS Safari, Chrome for Android and Samsung Internet already Web Share-ready, according to caniuse.com.

navigator.share support report on caniuse.com

Support for navigator.canShare is much more limited, as only Chrome for Android supports it at the moment.

navigator.canShare support report on caniuse.com

As usual, progressive enhancement is key here to start using these new features:

  • Make sure navigator.share exists before using it
  • Have a proper fallback for this feature in case it's not available

Exception thrown by navigator.share not being implemtended


The Web Share API is one of these features that helps breaking the barriers between web and native and that, while still in the works, can bring immediate improvement to how users experience the products we build: use responsibly, but surely use it πŸŽ‰.

Discussion (7)

Collapse
philnash profile image
Phil Nash

Did you notice that DEV uses the web share API? πŸ˜ƒ

Collapse
macargnelutti profile image
Matteo Cargnelutti Author

Ah ah good point ! I didn't even notice !

Collapse
philnash profile image
Phil Nash

I'm being a bit cheeky, only because I implemented it myself.

You might be interested in how though, I've built a web component that can wrap around traditional share links and take over if the web share API is available. It's called <web-share-wrapper> and I'd love your opinion on it.

Thread Thread
macargnelutti profile image
Matteo Cargnelutti Author • Edited

Just had a look. I think that is a great solution and a very good example of progressive enhancement. Well done 🎩!

Collapse
edgedrummer profile image
edgedrummer

Hi ! Thank you for this article. I have a question. I'm implementing this feature on a web page. I've noticed that all fields are well filled in android (title, text, url) but not in iOS. In Apple mail for example, object isn't filled, on Facebook Messenger, text isn't filled. Do you know if there is a solution for that ?
Thank you

Collapse
jatinhemnani01 profile image
Jatin Hemnani

any alternative to Webshare API?

Collapse
macargnelutti profile image
Matteo Cargnelutti Author

Fun game: count how many social media from the cover pic have disappeared since the picture was taken.