M.

Astro で外部スクリプトなしの SNS シェアボタンを作る(simple-icons でアイコンとブランドカラー)

このサイトの記事ページに、SNS のシェアボタンを付けました。

はてなブログから記事を移してきたとき、はてなでは標準で付いていたシェアボタンが無いことに気づきました。オリジナルの記事も書き始めたので、読んでくれた人に広めてもらいやすくしたいと思ったのがきっかけです。

ただし、公式のシェアウィジェットは使いたくありませんでした。各サービスのスクリプトを読み込むとページが重くなりますし、外部のスクリプトが動く分だけプライバシーポリシーに書くことも増えます。そこで 外部スクリプトを一切読み込まない、リンクだけのシェアボタン にしました。

環境:Astro 6.1 / Tailwind CSS 4.2 / simple-icons 16.34

完成形

記事の末尾に、次の6つのボタンを並べています。

  • X / Bluesky / Threads / Facebook / はてなブックマーク / LINE
  • それぞれのロゴアイコン付き
  • 背景はそれぞれのブランドカラー、文字とアイコンは白

この記事の下にあるボタンが、実際に動いているものです。

シェアはリンクだけでできる

各サービスには、URL にパラメータを付けて開くと投稿画面が出る「シェア用 URL」があります。シェアボタンの正体は、これへのリンクだけです。

サービスシェア用 URL
Xhttps://x.com/intent/post?text=タイトル&url=URL
Blueskyhttps://bsky.app/intent/compose?text=本文
Threadshttps://www.threads.net/intent/post?text=本文
Facebookhttps://www.facebook.com/sharer/sharer.php?u=URL
はてなブックマークhttps://b.hatena.ne.jp/entry/panel/?url=URL
LINEhttps://social-plugins.line.me/lineit/share?url=URL

Bluesky と Threads は URL 専用のパラメータが無いので、本文にタイトルと URL をまとめて入れます。どのパラメータも encodeURIComponent でエンコードしておきます。

アイコンは simple-icons をビルド時に埋め込む

ロゴは自分で描くと形が崩れるので、simple-icons を使いました。各ブランドの SVG パスとブランドカラーが入った npm パッケージです。

npm i -D simple-icons

siX のような名前で import すると、path(SVG のパス)と hex(ブランドカラー)が取れます。

import { siX } from "simple-icons";

siX.hex;  // "000000"
siX.path; // "M18.901 1.153h3.68l-8.04 9.19L24 ..."

Astro コンポーネントのフロントマターで import すれば、使われるのはビルド時だけです。出力される HTML にはインラインの <svg> が入るだけで、ブラウザで動く JavaScript はありません。

コンポーネント全体

src/components/ArticleShare.astro です。

---
import { siBluesky, siFacebook, siHatenabookmark, siLine, siThreads, siX } from "simple-icons";

interface Props {
    title: string;
    url: string;
}

const { title, url } = Astro.props;
const encodedUrl = encodeURIComponent(url);
const encodedText = encodeURIComponent(`${title} ${url}`);

const shares = [
    { name: "X", icon: siX, href: `https://x.com/intent/post?text=${encodeURIComponent(title)}&url=${encodedUrl}` },
    { name: "Bluesky", icon: siBluesky, href: `https://bsky.app/intent/compose?text=${encodedText}` },
    { name: "Threads", icon: siThreads, href: `https://www.threads.net/intent/post?text=${encodedText}` },
    { name: "Facebook", icon: siFacebook, href: `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}` },
    { name: "はてブ", icon: siHatenabookmark, href: `https://b.hatena.ne.jp/entry/panel/?url=${encodedUrl}` },
    { name: "LINE", icon: siLine, href: `https://social-plugins.line.me/lineit/share?url=${encodedUrl}` },
];
---

<section class="mt-12">
    <p class="mb-3">この記事をシェア</p>
    <ul class="flex flex-wrap gap-2">
        {
            shares.map((s) => (
                <li>
                    <a
                        href={s.href}
                        target="_blank"
                        rel="noopener noreferrer"
                        class="inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-bold text-white transition hover:opacity-80"
                        style={`background-color: #${s.icon.hex}`}
                    >
                        <svg role="img" viewBox="0 0 24 24" class="size-4 fill-current" aria-hidden="true">
                            <path d={s.icon.path} />
                        </svg>
                        {s.name}
                    </a>
                </li>
            ))
        }
    </ul>
</section>

ポイントは次の3つです。

  • ブランドカラーは style で入れる:Tailwind のクラスは動的に組み立てるとビルド時に検出されないので、hex はインラインの style で渡しています
  • アイコンは fill-current:SVG の塗りを文字色に合わせて、白い文字と同じ色にしています
  • aria-hidden="true":ボタンには「X」などの文字があるので、アイコンは読み上げ対象から外しています

記事ページ側では、記事の URL を組み立てて渡すだけです。

<ArticleShare title={title} url={pageURL} />

気をつけたところ

  • X と Threads はどちらも黒:ブランドカラーがどちらも 000000 なので、黒いボタンが2つ並びます。ロゴと文字で区別がつくので、そのままにしました
  • ロゴは各社の商標:simple-icons のアイコンデータ自体は CC0 ですが、ロゴは各社の商標です。シェアボタンのように「そのサービスへのリンク」として使う範囲にとどめています

まとめ

シェアボタンは、各サービスのシェア用 URL へのリンクを並べるだけで作れます。simple-icons を使えば、アイコンとブランドカラーもビルド時に埋め込めるので、外部スクリプトなしでも見た目はしっかりしたボタンになりました。

この記事をシェア

関連する記事

AI コード進行アプリを2年運用して分かったこと(GPT-4o から Claude へ、2024→2026)

キーワードからコード進行を作る Web アプリ Chord Eureka を、2024年12月の公開から2年近く運用してきました。GPT-4o 時代のコストと出力崩れへの対処、Claude への移行、temperature 廃止で本番が落ちた件、構造化出力、測ってから決めたモデル更新までを、git の履歴をもとに振り返ります。

Claude Code に GCP の課金を棚卸しさせたら、月1万円が半分になった(失敗込みの記録)

個人開発で使っている GCP の全プロジェクトを、Claude Code と一緒に横断して見直しました。gcloud での調査、ストレージの掃除、通信料の削減、そして CUD の二重契約という失敗まで。AI に任せられたこと・人間がやる必要があったことを整理します。

claude -p を評価器にして、AI の生成結果を930件自動採点した

コード進行アプリのキーワードボタンが本当に効いているのかを確かめるため、Claude Code の `claude -p` で930件を生成し、プログラムで採点しました。API キーを使わない生成のしかた、本番に近づけるためのオプション、Windows での落とし穴、AI に採点させない集計の考え方をまとめます。

テーマから探す