Opens an external site in a new window
Mental Health Awareness Month
“Community”
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links
  • Profile
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links

Svelte Share Buttons: using Web Share API with Fallback # Svelte Share Buttons: using Web Share API with Fallback #

blurry low resolution placeholder image Svelte Share Buttons
  1. Home Rodney Lab Home
  2. Blog Posts Rodney Lab Blog Posts
  3. SvelteKit SvelteKit Blog Posts
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Svelte Share Buttons: using Web Share API with Fallback #

Updated 3 months ago
13 minute read
Gunning Fog Index: 4.9
Content by Rodney
blurry low resolution placeholder image Author Image: Rodney from Rodney Lab
SHARE:

🤗 What is the Web Share API? #

In this post, we see how you can add Svelte share buttons to your Svelte-based app. We will follow a roll-your-own approach here, using inbuilt browser APIs, rather than adding extra packages or dependencies. We will work in SvelteKit though our Svelte components can just as easily be used in Astro Svelte apps.

We add buttons, to a blog starter, which let site visitors share blog posts with their friends and followers on WhatsApp, Telegram and Twitter as well as Facebook. That functionality works in any browser, relying on just JavaScript. As well as that, we make use of the relatively new Web Share API. On the visitor’s mobile; this will bring up a menu, making it easy to share your site on any suitable apps they have installed. We are going for a progressive enhancement approach. This means mobile (and Safari on desktop) will show the Web Share API button, while browsers yet to support it will show our share buttons instead.

🧱 What we’re Building #

Please enable JavaScript to watch the video 📼

Svelte Share Buttons: using Web Share API with Fallback: Building

I mentioned we are working in SvelteKit using the MDsveX blog starter. If Astro is your preferred tool for building Svelte sites, start with the Astro Svelte Markdown starter  instead. Of course, if you have an existing Svelte app, you can create a feature branch and add this functionality there. Anyway, to start, let’s clone a repo:

    
git clone https://github.com/rodneylab/sveltekit-blog-mdx.git sveltekit-share-buttons
cd sveltekit-share-buttons
pnpm install
cp .env.EXAMPLE .env
pnpm run dev

With that done, we will start by adding the fallback share button functionality. We will run through adding Twitter in detail, then sketch over adding other networks. If you want to add a popular network not mentioned, drop a comment below, and I will see what I can do. Equally, feel free to submit a pull request to the repo if you code up support for a well-known network, not already implemented.

🧩 Initial Share Button Component #

To get the ball rolling, let’s create a src/lib/components/ShareButtons folder and inside it add an index.svelte file. This file will ultimately contain the logic for the Web Share progressive enhancement, as well as the fallbacks. Progressive enhancement expresses a similar sentiment to graceful degradation. The idea is, we want to support a new feature which does not currently enjoy wide support. We have a baseline which supports all (or most) devices, then the progressive enhancement offers the new feature, but only where the user device supports it.

To get going, paste this code into the new file:

src/lib/components/ShareButtons/index.svelte
svelte
    
1 <script>
2 import Twitter from '$lib/components/ShareButtons/Twitter.svelte';
3 import website from '$lib/config/website';
4
5 const { siteUrl } = website;
6
7 let { slug, title } = $props();
8
9 let url = $derived(`${siteUrl}/${slug}`);
10 </script>
11
12 <aside aria-label="Share buttons" class="container">
13 <div class="wrapper">
14 Share: <div class="buttons">
15 <Twitter {url} {title} />
16 </div>
17 </div>
18 </aside>

Here is some optional styling which you can paste at the end of the file:

src/lib/components/ShareButtons/index.svelte — click to expand code.
src/lib/components/ShareButtons/index.svelte
svelte
    
21 <style lang="scss">
22 .container {
23 display: flex;
24 flex-direction: row;
25 margin-top: variables.$spacing-12;
26 width: variables.$max-width-full;
27 }
28 .wrapper {
29 display: flex;
30 flex-direction: row;
31 margin-left: auto;
32 font-weight: variables.$font-weight-bold;
33 font-size: variables.$font-size-2;
34 }
35 .buttons {
36 margin-left: variables.$spacing-4;
37 }
38
39 button {
40 background: transparent;
41 border-style: none;
42 transition: all 0.2s ease-in-out;
43 }
44
45 @media (prefers-reduced-motion: reduce) {
46 button {
47 transition: all 2s ease-in-out;
48 }
49 }
50
51 button:focus,
52 button:hover {
53 transform: scale(1.1);
54 }
55 </style>

This will not work yet — we need to create the Twitter share button component. Nonetheless, let’s add the ShareButton component to our blog post template now:

src/lib/components/BlogPost.svelte
svelte
    
1 <script>
2 import BannerImage from '$lib/components/BannerImage.svelte';
3 import SEO from '$lib/components/SEO/index.svelte';
4 import ShareButtons from '$lib/components/ShareButtons/index.svelte';
5 import readingTime from 'reading-time';
src/lib/components/BlogPost.svelte
svelte
    
73 <BannerImage {imageData} />
74 <h1>{title}</h1>
75 <ShareButtons {slug} {title} />

With that basic wiring up done, we will next create the Twitter share button component. The other components work similarly, though the Twitter API supports the most customization, so it provides a good starting point.

🐦 Twitter Share Button Component #

This button will be part of the fallback; as such, we will not show it on devices which support the Web Share API. Currently, on MacOS, Safari does support the API, so test this part in Firefox and Chrome. The Twitter code, together with the other share button components, are based off the nygardk/react-share  GitHub repo by Klaus Nygård.

src/lib/components/ShareButtons/Twitter.svelte
svelte
    
1 <script>
2 import TwitterIcon from '$lib/components/Icons/Twitter.svelte';
3
4 let {
5 hashtags = [], // array of hashtags exclude '#' e.g. ['svelte', 'askRodney']
6 quote = undefined,
7 related = [], // array of Twitter users (including '@')
8 title, // text in Tweet
9 url,
10 via = '',
11 } = $props(); // include '@' e.g. '@askRodney'
12
13 const TWITTER_BLUE = '#00aced';
14
15 const baseUrl = 'https://x.com/share';
16 const parametersObject = {
17 url,
18 ...(hashtags.length > 0 ? { hashtags: hashtags.join(',') } : {}),
19 quote,
20 text: title,
21 ...(related.length > 0 ? { related: related.join(',') } : {}),
22 ...(via.length > 0 ? { via: via.slice(1) } : {}),
23 };
24
25 const params = Object.entries(parametersObject)
26 .filter(([, value]) => value ?? false)
27 .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
28 .join('&');
29
30 const urlWithParameters = params === '' ? baseUrl : `${baseUrl}?${params}`;
31
32 function handleClick() {
33 const config = {
34 height: 550,
35 width: 400,
36 location: 'no',
37 toolbar: 'no',
38 status: 'no',
39 directories: 'no',
40 menubar: 'no',
41 scrollbars: 'yes',
42 resizable: 'no',
43 centerscreen: 'yes',
44 chrome: 'yes',
45 };
46 return window.open(
47 urlWithParameters,
48 '',
49 Object.keys(config)
50 .map((key) => `${key}=${config[key]}`)
51 .join(','),
52 );
53 }
54 </script>
55
56 <button onclick={handleClick}
57 ><span class="screen-reader-text">Share on X (Twitter)</span><TwitterIcon
58 colour={TWITTER_BLUE}
59 width={48}
60 /></button
61 >
62
63 <style lang="scss">
64 button {
65 background: transparent;
66 border-style: none;
67 transition: all 0.2s ease-in-out;
68 }
69 @media (prefers-reduced-motion: reduce) {
70 button {
71 transition: all 2s ease-in-out;
72 }
73 }
74
75 button:focus,
76 button:hover {
77 transform: scale(1.1);
78 }
79 @media screen and (max-width: $desktop-breakpoint) {
80 button {
81 padding-left: $spacing-2;
82 padding-right: $spacing-2;
83 }
84 }
85 </style>

In line 2 we import an SVG X Twitter icon, already used in the project. See the post on Deno SVG Sprite Sheets to learn more about adding optimised SVG assets to pages.

The Twitter API has the most bells and whistles: you can include hashtags, quotes and related accounts as well as a via Twitter account. I have added some comments in the code to explain how to use these. Here, we’ll just focus on adding the text (title prop) and URL.

Twitter Customizations #

Lines 16 – 23 (above) build up the query parameters for the URL which we need to send to Twitter to share the post. Because this is a URL, some characters are not allowed, and we have to encode them. In line 27, we make use of encodeURIComponent to URL encode the keys and parameters  for us.

The handleClick code in lines 32 – 53 brings up a new window on Twitter’s site which lets the visitor log in (if they are not already logged in) and share. The sizes are sensible defaults which work on different sized devices, so you will probably not need to adjust these.

The other components will be similar, though with differing baseUrl (see line 15). For improved accessibility, include some screen reader text on all buttons (as in line 57). This will not be visible, though screen readers will announce it, helping screen reader users know what the button does.

🔘 Other Network Buttons #

We will skim over the other networks now, in fact, we will only point out details which are different. Then in the following section we will add them into the principal component and also wire up the Web Share API.

Facebook #

src/lib/components/ShareButtons/Facebook.svelte — click to expand code.
src/lib/components/ShareButtons/Facebook.svelte
svelte
    
1 <script>
2 import FacebookIcon from '$lib/components/Icons/Facebook.svelte';
3
4 let { hashtag = '', quote = '', url } = $props();
5
6 const FACEBOOK_BLUE = '#3b5998';
7
8 const baseUrl = 'https://www.facebook.com/sharer/sharer.php';
9 let parametersObject = $derived({
10 u: url,
11 ...(quote !== '' ? { quote } : {}),
12 ...(hashtag !== '' ? { hashtag } : {}),
13 });
14
15 let params = $derived(
16 Object.entries(parametersObject)
17 .filter(([, value]) => value ?? false)
18 .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
19 .join('&'),
20 );
21
22 let urlWithParameters = $derived(params === '' ? baseUrl : `${baseUrl}?${params}`);
23
24 function handleClick() {
25 const config = {
26 height: 550,
27 width: 400,
28 location: 'no',
29 toolbar: 'no',
30 status: 'no',
31 directories: 'no',
32 menubar: 'no',
33 scrollbars: 'yes',
34 resizable: 'no',
35 centerscreen: 'yes',
36 chrome: 'yes',
37 };
38 return window.open(
39 urlWithParameters,
40 '',
41 Object.keys(config)
42 .map((key) => `${key}=${config[key]}`)
43 .join(','),
44 );
45 }
46 </script>
47
48 <button onclick={handleClick}
49 ><span class="screen-reader-text">Share on Facebook</span><FacebookIcon
50 colour={FACEBOOK_BLUE}
51 width={48}
52 /></button
53 >
54
55 <style lang="scss">
56 button {
57 background: transparent;
58 border-style: none;
59 transition: all 0.2s ease-in-out;
60 }
61
62 @media (prefers-reduced-motion: reduce) {
63 button {
64 transition: all 2s ease-in-out;
65 }
66 }
67
68 button:focus,
69 button:hover {
70 transform: scale(1.1);
71 }
72
73 @media screen and (max-width: $desktop-breakpoint) {
74 button {
75 padding-left: $spacing-2;
76 padding-right: $spacing-2;
77 }
78 }
79 </style>

Telegram #

src/lib/components/ShareButtons/Telegram.svelte — click to expand code.
src/lib/components/ShareButtons/Telegram.svelte
svelte
    
1 <script>
2 import TelegramIcon from '$lib/components/Icons/Telegram.svelte';
3
4 let { url, title } = $props();
5
6 const TELEGRAM_BLUE = '#49a9e9';
7
8 const baseUrl = 'https://telegram.me/share/url';
9 let parametersObject = $derived({
10 url,
11 text: title,
12 });
13
14 let params = $derived(
15 Object.entries(parametersObject)
16 .filter(([, value]) => value ?? false)
17 .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
18 .join('&'),
19 );
20
21 let urlWithParameters = $derived(params === '' ? baseUrl : `${baseUrl}?${params}`);
22
23 function handleClick() {
24 const config = {
25 height: 550,
26 width: 400,
27 location: 'no',
28 toolbar: 'no',
29 status: 'no',
30 directories: 'no',
31 menubar: 'no',
32 scrollbars: 'yes',
33 resizable: 'no',
34 centerscreen: 'yes',
35 chrome: 'yes',
36 };
37 return window.open(
38 urlWithParameters,
39 '',
40 Object.keys(config)
41 .map((key) => `${key}=${config[key]}`)
42 .join(','),
43 );
44 }
45 </script>
46
47 <button onclick={handleClick}
48 ><span class="screen-reader-text">Share on Telegram</span><TelegramIcon
49 colour={TELEGRAM_BLUE}
50 width={48}
51 /></button
52 >
53
54 <style lang="scss">
55 button {
56 background: transparent;
57 border-style: none;
58 transition: all 0.2s ease-in-out;
59 }
60
61 @media (prefers-reduced-motion: reduce) {
62 button {
63 transition: all 2s ease-in-out;
64 }
65 }
66
67 button:focus,
68 button:hover {
69 transform: scale(1.1);
70 }
71
72 @media screen and (max-width: $desktop-breakpoint) {
73 button {
74 padding-left: $spacing-2;
75 padding-right: $spacing-2;
76 }
77 }
78 </style>

WhatsApp #

src/lib/components/ShareButtons/Whatsapp.svelte — click to expand code.
src/lib/components/ShareButtons/Whatsapp.svelte
svelte
    
1 <script>
2 import { browser } from '$app/env';
3 import WhatsappIcon from '$lib/components/Icons/Whatsapp.svelte';
4 import { isMobileOrTablet } from '$lib/utilities/device';
5
6 const WHATSAPP_GREEN = '#25D366';
7
8 let { url, title } = $props();
9
10 let baseUrl = $derived(
11 browser && isMobileOrTablet()
12 ? 'https://api.whatsapp.com/send'
13 : 'https://web.whatsapp.com/send',
14 );
15 let parametersObject = $derived({
16 text: title ? title + ' ' + url : url,
17 });
18
19 let params = $derived(
20 Object.entries(parametersObject)
21 .filter(([, value]) => value ?? false)
22 .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
23 .join('&'),
24 );
25
26 let urlWithParameters = $derived(params === '' ? baseUrl : `${baseUrl}?${params}`);
27
28 function handleClick() {
29 const config = {
30 height: 550,
31 width: 400,
32 location: 'no',
33 toolbar: 'no',
34 status: 'no',
35 directories: 'no',
36 menubar: 'no',
37 scrollbars: 'yes',
38 resizable: 'no',
39 centerscreen: 'yes',
40 chrome: 'yes',
41 };
42 return window.open(
43 urlWithParameters,
44 '',
45 Object.keys(config)
46 .map((key) => `${key}=${config[key]}`)
47 .join(','),
48 );
49 }
50 </script>
51
52 <button onclick={handleClick}
53 ><span class="screen-reader-text">Share on Whatsapp</span><WhatsappIcon
54 colour={WHATSAPP_GREEN}
55 width={48}
56 /></button
57 >
58
59 <style lang="scss">
60 button {
61 background: transparent;
62 border-style: none;
63 transition: all 0.2s ease-in-out;
64 }
65 @media (prefers-reduced-motion: reduce) {
66 button {
67 transition: all 2s ease-in-out;
68 }
69 }
70
71 button:focus,
72 button:hover {
73 transform: scale(1.1);
74 }
75
76 @media screen and (max-width: $desktop-breakpoint) {
77 button {
78 padding-left: $spacing-2;
79 padding-right: $spacing-2;
80 }
81 }
82 </style>

There is not already a WhatsApp icon in the starter. Add this code, or create your own using your preferred icon set:

src/lib/components/Icons/Whatsapp.svelte — click to expand code.
src/lib/components/Icons/Whatsapp.svelte
svelte
    
1 <script>
2 let {
3 label = 'whatsapp icon',
4 colour = 'inherit',
5 ariaHidden = false,
6 width = 24,
7 height = width,
8 } = $props();
9 </script>
10
11 <div class="logo">
12 <svg
13 aria-hidden={ariaHidden}
14 color={colour}
15 aria-label={label}
16 role="img"
17 {width}
18 {height}
19 viewBox="0 0 24 24"
20 fill="none"
21 >
22 <use href="/sprite.svg#whatsapp" />
23 </svg>
24 </div>
25
26 <style>
27 .logo {
28 display: flex;
29 align-items: center;
30 }
31 </style>

You also need to update the SVG sprite sheet, adding WhatsApp (and Share, for

later) icons. Add these lines within the <defs> element of

assets/sprite.svg:

    
<!-- https://api.iconify.design/lucide:share-2.svg -->
<symbol viewBox="0 0 24 24" id="share">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<circle cx="18" cy="5" r="3" />
<circle cx="6" cy="12" r="3" />
<circle cx="18" cy="19" r="3" />
<path d="m8.59 13.51l6.83 3.98m-.01-10.98l-6.82 3.98" />
</g>
</symbol>
<!-- https://api.iconify.design/simple-icons:whatsapp.svg -->
<symbol viewBox="0 0 24 24" id="whatsapp">
<path fill="currentColor"
d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967c-.273-.099-.471-.148-.67.15c-.197.297-.767.966-.94 1.164c-.173.199-.347.223-.644.075c-.297-.15-1.255-.463-2.39-1.475c-.883-.788-1.48-1.761-1.653-2.059c-.173-.297-.018-.458.13-.606c.134-.133.298-.347.446-.52c.149-.174.198-.298.298-.497c.099-.198.05-.371-.025-.52c-.075-.149-.669-1.612-.916-2.207c-.242-.579-.487-.5-.669-.51a12.8 12.8 0 0 0-.57-.01c-.198 0-.52.074-.792.372c-.272.297-1.04 1.016-1.04 2.479c0 1.462 1.065 2.875 1.213 3.074c.149.198 2.096 3.2 5.077 4.487c.709.306 1.262.489 1.694.625c.712.227 1.36.195 1.871.118c.571-.085 1.758-.719 2.006-1.413c.248-.694.248-1.289.173-1.413c-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214l-3.741.982l.998-3.648l-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884c2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413Z" />
</symbol>

Then, finally create an optimised sprite sheet at static/sprite.svg, by

running:

    
pnpm vite-node minify-script.ts

Also for WhatsApp, there are different API URLs depending on whether the visitor is using a mobile device or not. We make use of a utility function to check the type of device the user has. Create this file if you added the WhatsApp share button code above to your app:

src/lib/utilities/device.js
javascript
    
1 /**
2 * Returns true if the device is thought to be a mobile or tablet
3 * @returns {boolean}
4 */
5 export function isMobileOrTablet() {
6 return /(android|iphone|ipad|mobile)/i.test(navigator.userAgent);
7 }

🔨 Pulling it all Together #

We are going back to src/lib/components/ShareButtons/index.svelte now to tie the new buttons in. Feel free to omit any networks you will not need on your app here.

src/lib/components/ShareButtons/index.svelte
svelte
    
1 <script>
2 import Facebook from '$lib/components/ShareButtons/Facebook.svelte';
3 import Telegram from '$lib/components/ShareButtons/Telegram.svelte';
4 import Twitter from '$lib/components/ShareButtons/Twitter.svelte';
5 import Whatsapp from '$lib/components/ShareButtons/Whatsapp.svelte';
6 import website from '$lib/config/website';
7
8 const { siteTitle, siteUrl } = website;
9
10 let { slug, title } = $props();
11
12 const url = `${siteUrl}/${slug}`;
13 </script>
14
15 <aside aria-label="Share buttons" class="container">
16 <div class="wrapper">
17 Share: <div class="buttons">
18 <Twitter {url} {title} /><Facebook {url} /><Whatsapp {url} {title} />
19 <Telegram {url} {title} />
20 </div>
21 </div>
22 </aside>

I think it will be clear what we are doing here, but let me know if I have forgotten to explain something!

🕸 Web Share API #

The final missing piece is the Web Share button. We will add a webShareAPISupported boolean variable with a reactive declaration . This requires access to the browser navigator object, so will not work when the code is running server-side. SvelteKit provides the browser variable defined in $app/env which we make use of here. If you are working in Astro, check for ssr using this snippet:

    
// ASTRO ONLY - IGNORE FOR SVELTEKIT
const ssr = import.meta.env.SSR;

Remember when browser in the SvelteKit code is true, ssr will be false (and vice verse).

Anyway, let’s update the file:

src/lib/components/ShareButtons/index.svelte
svelte
    
1 <script>
2 import { browser } from '$app/environment';
3 import ShareIcon from '$lib/components/Icons/Share.svelte';
4 import Facebook from '$lib/components/ShareButtons/Facebook.svelte';
5 import Telegram from '$lib/components/ShareButtons/Telegram.svelte';
6 import Twitter from '$lib/components/ShareButtons/Twitter.svelte';
7 import Whatsapp from '$lib/components/ShareButtons/Whatsapp.svelte';
8 import website from '$lib/config/website';
9
10 const { siteTitle, siteUrl } = website;
11
12 let { slug, title } = $props();
13
14 let webShareAPISupported = $state(browser && typeof navigator.share !== 'undefined');
15
16 const handleWebShare = async () => {
17 try {
18 navigator.share({
19 title,
20 text: `Shared from ${siteTitle}`,
21 url,
22 });
23 } catch {
24 webShareAPISupported = false;
25 }
26 };
27 let url = $derived(`${siteUrl}/${slug}`);
28 </script>
29
30 <aside class="container">
31 <div class="wrapper">
32 Share: <div class="buttons">
33 {#if webShareAPISupported}
34 <button onclick={handleWebShare}
35 ><span class="screen-reader-text">Share</span><ShareIcon width={48} /></button
36 >
37 {:else}
38 <Twitter {url} {title} /><Facebook {url} /><Whatsapp {url} {title} />
39 <Telegram {url} {title} />{/if}
40 </div>
41 </div>
42 </aside>

What have we got here? #

In lines 33 – 39, we have a guard so if webShareAPISupported is false, the user will see the share buttons we previously defined. On the other hand, if it is true, the user sees the share button, which we will add in a moment.

When the use clicks or taps the share button, the handleWebShare function is invoked. This is asynchronous, so it is best practice to include try/catch blocks. If for some reason, the share fails, there is no issue! Remember, we have our fallback, so just show the share buttons for the networks we added initially. Lines 18 – 22 have the core Web Share code.

Sharing via the API #

The Web Share API lets users share links, text, and files . We focus on sharing text and links here. To share a file, just add an extra files field to the share object. We share both a link and some related text. You can opt to share either one of these on its own and drop the other (some browsers do not yet support text, though). You see that the API is fairly simple and there is not much more left to explain… the browsers do all the heavy lifting! The final thing worth a mention is the check for support in line 14. To check the latest browser support, see MDN Web Share API docs .

Share Icon #

Before we can test, we need to put the missing share icon into the project (feel free to swap this out, using your preferred collection):

src/lib/components/Icon/Share.svelte
svelte
    
1 <script>
2 let {
3 label = 'share icon',
4 colour = 'inherit',
5 ariaHidden = false,
6 width = 24,
7 height = width,
8 } = $props();
9 </script>
10
11 <div class="logo">
12 <svg
13 aria-hidden={ariaHidden}
14 color={colour}
15 aria-label={label}
16 role="img"
17 {width}
18 {height}
19 viewBox="0 0 24 24"
20 fill="none"
21 >
22 <use href="/sprite.svg#share" />
23 </svg>
24 </div>
25
26 <style>
27 .logo {
28 display: flex;
29 align-items: center;
30 }
31 </style>

🗳 Poll #

Which browsers do you test your apps in?
Voting reveals latest results.

💯 Svelte Share Buttons: Test #

You should now be able to see the share buttons if you open any of the blog posts in a browser. To test on desktop, at the time of writing the WebShare API was not supported on Firefox and Chrome, so these are good for testing the fallback buttons. Safari on desktop does support the Web Share API, so is fantastic for testing that button. Also, try deploying your app to a staging environment to test a few mobile browsers.

Please enable JavaScript to watch the video 📼

Svelte Share Buttons: using Web Share API with Fallback: Testing

🙌🏽 Svelte Share Buttons: Wrapup #

In this post we looked at:

  • how to add share buttons to a Svelte app with progressive enhancement,
  • using the Web Share API to share from a Svelte app,
  • adding fallback share icons with an SVG sprite sheet.

I do hope there is at least one thing in this article which you can use in your work or a side project. Also, let me know if you feel more explanation of the config is needed.

This post came from a request in a comment on another post, so do drop a comment below if there is something else you would like to see a video or post on.

You can see the full SvelteKit code for this project on the Rodney Lab Git Hub repo . If you run into any issues, you can drop a comment below as well as reach out for a chat on Element . Also, Twitter @mention  if you have suggestions for improvements or questions.

🏁 Svelte Share Buttons: Summary #

What is the Web Share API? #

The Web Share API offers a convenient way for web developers to allow site visitors to share text, URLs, and files. The API needs to be invoked via a user action, such a tapping a button. Once invoked, supporting browsers show a native dialogue allowing users to share using apps installed on their device. The developer needs no prior knowledge of which apps are available on the user device. The user experience is ideal, allowing them to share content with friends, family, and followers using their favourite apps and social networks.

Which browsers currently support the Web Share API? #

The Web Share API is supported on some, but not all browsers. Mobile browsers tend to have more favourable support. Safari on iOS and Chrome, Firefox and Opera on Android all support it. On top, Safari and Opera offer full desktop support, while Chrome and Edge have partial support. That’s for sharing URLs. Firefox for Android does not support file sharing via the Web Share API at the time of writing, and only Safari offers full desktop support.

How can you add the Web Share API with Progressive Enhancement? #

To provide the best overall experience for all users, it is worth adding JavaScript based share buttons (without use of the Web Share API) as a base case. These buttons need to make use of the social networks’ own APIs. To offer an enhanced experience to users with devices which support the API, add a check for support and only show the corresponding share button where it is supported. While a single share button may suffice when the Web Share API is supported, buttons for multiple popular networks invoking that network’s own API are needed in the fallback.

🙏🏽 Feedback #

If you have found this video useful, see links below for further related content on this site. I do hope you learned one new thing from the video. Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on Twitter, giving me a mention, so I can see what you did. Finally, be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please consider supporting me through Buy me a Coffee.

blurry low resolution placeholder image ask Rodney X (formerly Twitter) avatar

Rodney

@askRodney

Just dropped a new post taking you through how to roll-your-own sharing in your ❤️ Svelte app with Web Share API support as a progressive enhancement.

Includes fallbacks for the Facebook, Telegram, Twitter & WhatsApp share APIs.

Hope you find it useful!

https://t.co/5eZGjznGoB

— Rodney (@askRodney) April 8, 2022

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter and also askRodney on Telegram . Also, see further ways to get in touch with Rodney Lab. I post regularly on SvelteKit as well as Search Engine Optimization among other topics. Also, subscribe to the newsletter to keep up-to-date with our latest projects.

Thanks for reading this post. I hope you found it valuable. Please get in touch with your feedback and suggestions for posts you would like to see. Read more about me …

blurry low resolution placeholder image Rodney from Rodney Lab
TAGS:
SVELTEKIT

Likes:

Likes

  • Antonio profile avatar
Likes provided by Mastodon & X via Webmentions.

Related Posts

blurry low resolution placeholder image SvelteKit SVG Icons: using Iconify and Icônes with Svelte

SvelteKit SVG Icons: using Iconify and Icônes with Svelte

sveltekit
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Leave a comment …

Your information will be handled in line with our Privacy Policy .

Ask for more

1 Nov 2022 — Astro Server-Side Rendering: Edge Search Site
3 Oct 2022 — Svelte eCommerce Site: SvelteKit Snipcart Storefront
1 Sept 2022 — Get Started with SvelteKit Headless WordPress

Copyright © 2020 – 2025 Rodney Johnson. All Rights Reserved. Please read important copyright and intellectual property information.

  • Home
  • Profile
  • Plus +
  • Newsletter
  • Contact
  • Links
  • Terms of Use
  • Privacy Policy
We use cookies  to enhance visitors’ experience. Please click the “Options” button to make your choice.  Learn more here.