協助使用者分享目前瀏覽的網站

讓使用者分享目前瀏覽的網站是常見的網頁應用程式模式,許多新聞網站、網誌或購物網站都提供這項功能。連結是網路的超能力之一,因此我們希望從社交網站上看到分享連結的使用者,或是透過即時通訊訊息,甚至是透過電子郵件收到連結的使用者,都能為網站帶來流量。

使用 Web Share API

使用者可以透過 Web Share API 分享資料,例如目前所在網頁的網址,以及標題和說明文字。Web Share API 的 navigator.share() 方法會叫用裝置的分享機制。這個函式會傳回 Promise,並採用單一引數 (要分享的資料)。可能的值為:

  • url:代表要分享網址的字串。
  • text:代表要分享文字的字串。
  • title:代表要分享的標題的字串。瀏覽器可能會忽略這項設定。

Browser Support

  • Chrome: 128.
  • Edge: 93.
  • Firefox: behind a flag.
  • Safari: 12.1.

Source

使用社群網站的分享意圖

目前只有部分瀏覽器支援 Web Share API。因此,替代方案是與目標對象最常使用的社群網站整合。Twitter 就是一個常見的例子,其網頁意圖網址可分享文字和網址。這個方法通常是建立網址,然後在瀏覽器中開啟。

使用者介面注意事項

最佳做法是根據作業系統供應商的 UI 指南,採用平台既有的共用圖示。

    Windows 圖示

    Apple 圖示

    Android 和其他作業系統

漸進增強

如果支援 Web Share API,程式碼片段就會使用該 API,否則會改用 Twitter Web Intent 網址。

// DOM references
const button = document.querySelector('button');
const icon = button.querySelector('.icon');
const canonical = document.querySelector('link[rel="canonical"]');

// Find out if the user is on a device made by Apple.
const isMac = navigator.platform.toLowerCase().includes('mac');

// Find out if the user is on a Windows device.
const isWin = navigator.platform.toLowerCase().includes('win');

// For Apple devices or Windows, use the platform-specific share icon.
icon.classList.add(`share${isMac? 'mac' : (isWin? 'windows' : '')}`);

button.addEventListener('click', async () => {
  // Title and text are identical, since the title may actually be ignored.
  const title = document.title;
  const text = document.title;
  // Use the canonical URL, if it exists, else, the current location.
  const url = canonical?.href || location.href;

  // Feature detection to see if the Web Share API is supported.
  if ('share' in navigator) {
    try {
      await navigator.share({
        url,
        text,
        title,
      });
      return;
    } catch (err) {
      // If the user cancels, an `AbortError` is thrown.
      if (err.name !== "AbortError") {
        console.error(err.name, err.message);
      }
    }
  }
  // Fallback to use Twitter's Web Intent URL.
  const shareURL = new URL('https://twitter.com/intent/tweet');
  const params = new URLSearchParams();
  params.append('text', text);
  params.append('url', url);
  shareURL.search = params;
  window.open(shareURL, '_blank', 'popup,noreferrer,noopener');
});

示範

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>How to let the user share the website they are on</title>
    <link rel="stylesheet" href="style.css" />
    <!-- TODO: Devsite - Removed inline handlers -->
    <!-- <script src="script.js" defer></script> -->
  </head>
  <body>
    <h1>How to let the user share the website they are on</h1>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin at libero
      eget ante congue molestie. Integer varius enim leo. Duis est nisi,
      ullamcorper et posuere eu, mattis sed lorem. Lorem ipsum dolor sit amet,
      consectetur adipiscing elit. In at suscipit erat, et sollicitudin lorem.
    </p>
    <img src="https://placekitten.com/400/300" width=400 height=300>
    <p>
      In euismod ornare scelerisque. Nunc imperdiet augue ac porttitor
      porttitor. Pellentesque habitant morbi tristique senectus et netus et
      malesuada fames ac turpis egestas. Curabitur eget pretium elit, et
      interdum quam.
    </p>
    <hr />
    <button type="button"><span class="icon"></span>Share</button>
  </body>
</html>

CSS


        :root {
  color-scheme: dark light;
}

html {
  box-sizing: border-box;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  margin: 1rem;
  font-family: system-ui, sans-serif;
}

img,
video {
  height: auto;
  max-width: 100%;
}

button {
    display: flex;
    background: #9c9c9c;
    padding: 12px;
    color:  #fff;
    border: 1px solid #9c9c9c;
    border-radius: 8px;
}

button .icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  background-size: 1em;
}

button:hover {
  background: #5089d3ff;
}

@media (prefers-color-scheme: dark) {
  button .icon {
    filter: invert();
  }
}

.share {
  background-image: url('windows.svg');
  color: #fff;
}

.sharemac {
  background-image: url('mac.svg');
  color: #fff;
}
        

JS


        // DOM references
const button = document.querySelector('button');
const icon = button.querySelector('.icon');
const canonical = document.querySelector('link[rel="canonical"]');

// Find out if the user is on a device made by Apple.
const isMac = navigator.platform.toLowerCase().includes('mac');

// Find out if the user is on a Windows device.
const isWin = navigator.platform.toLowerCase().includes('win');

// For Apple devices or Windows, use the platform-specific share icon.
icon.classList.add(`share${isMac? 'mac' : (isWin? 'windows' : '')}`);

button.addEventListener('click', async () => {
  // Title and text are identical, since the title may actually be ignored.
  const title = document.title;
  const text = document.title;
  // Use the canonical URL, if it exists, else, the current location.
  const url = canonical?.href || location.href;

  // Feature detection to see if the Web Share API is supported.
  if ('share' in navigator) {
    try {
      await navigator.share({
        url,
        text,
        title,
      });
      return;
    } catch (err) {
      // If the user cancels, an `AbortError` is thrown.
      if (err.name !== "AbortError") {
        console.error(err.name, err.message);
      }
    }
  }
  // Fallback to use Twitter's Web Intent URL.
  const shareURL = new URL('https://twitter.com/intent/tweet');
  const params = new URLSearchParams();
  params.append('text', text);
  params.append('url', url);
  shareURL.search = params;
  window.open(shareURL, '_blank', 'popup,noreferrer,noopener');
});