WordPressで作成しHTML化してFirebaseHostingしている本サイトに、HTMLとJavaScriptで以下のソーシャルボタンを追加しました。

  • はてなブックマーク
  • はてなスター
  • Pocket
  • Twitter

コードの埋め込み方法

WordPressなのでphpを直接修正しても良いのですが、どこを修正したか分からなくなりがちなので、Insert Headers And Footersというプラグインを使ってHTMLを埋め込むことにしました。
このプラグインは、<head>の最後<body>の最初<body>の最後、のいずれかの場所にHTMLコードを差し込むことができる、とてもシンプルなプラグインです。
これを使って、<body>の最後に取得したコードを埋め込みました。

はてなブックマーク

https://b.hatena.ne.jp/guide/bbutton
でデザインを選んで、コードスニペットを取得できます。

<a href="https://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="touch-counter" title="このエントリーをはてなブックマークに追加"><img src="https://b.st-hatena.com/images/v4/public/entry-button/button-only@2x.png" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a><script type="text/javascript" src="https://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script>

あとは、このコードをボタンを表示したい場所に埋め込むだけで完了です。

はてなスター

http://developer.hatena.ne.jp/ja/documents/star/misc/hatenastarjs
にやり方が書いてありますが、そのまま実装すると↓↓のように少しクラシックな見た目になってしまいます。

見た目は多少こだわりたいので、上記ドキュメントを取り込みつつ、JavaScriptとCSSで見た目を整えました。
出来上がったものが↓↓です。

実装は多少長くなりますが、以下の通りです。

<div id="hatena-star-container"></div>

<style type="text/css">
    #hatena-star-container {
        max-width: 200px;
        line-height: initial;
    }
    #hatena-star-color-pallet {
        display: none;
    }
    .hatena-star-add-button {
        margin: 0 !important;
    }
    .hatena-big-star-star-container {
        display: inline-block;
        position: relative;
        width: 20px;
        height: 20px;
        margin-left: 2px;
        vertical-align: middle;
        border-radius: 2px;
        overflow: hidden;
    }
    .hatena-star-user {
        position: absolute;
        width: 20px;
        height: 20px;
        z-index: 10;
        border-radius: 3px;
    }
    .hatena-star-star-refined {
        position: absolute;
        z-index: 11;
        top: 10px;
    }
</style>
<script type="text/javascript" src="http://s.hatena.ne.jp/js/HatenaStar.js"></script>
<script type="text/javascript">
    Hatena.Star.SiteConfig = {
        entryNodes: {
            'div.site-content': {
                uri: 'window.location',
                title: 'document.title',
                container: 'div#hatena-star-container'
            }
        }
    };
    (() => {
        const observer = new MutationObserver((mutations) => {
            const addButtonEl = document.querySelector('.hatena-star-add-button');
            addButtonEl.src = 'https://cdn.blog.st-hatena.com/images/theme/star/hatena-star-add-button.svg';
            document.querySelectorAll(".hatena-star-star").forEach(starEl => {
                if (!starEl.alt) return;
                starEl.outerHTML = `<span class="hatena-big-star-star-container"><img src="https://cdn.profile-image.st-hatena.com/users/${starEl.alt}/profile.png" class="hatena-star-user"><img src="https://s.hatena.ne.jp/images/star.gif" alt="${starEl.alt}" class="hatena-star-star-refined"></span>`;
            });
        });
        const containerEl = document.querySelector('#hatena-star-container');
        observer.observe(containerEl, {childList: true, subtree: true});
    })();
</script>

まずは、ドキュメント通りの部分を説明します。

  • entryNodesの直下のCSSセレクタ(div.site-content
    • 合致する要素の数だけ☆アイコンが表示される
  • uri(window.location
    • 登録対象のURL。URLが記載された要素をCSSセレクタで指定する
    • 特殊なセレクタとして、window.locationdocument.locationも使える
  • title(document.title
    • 登録対象のタイトル。タイトルが記載された要素をCSSセレクタで指定する
    • 特殊なセレクタとして、document.titleが使える
  • container(div#hatena-star-container
    • ☆アイコンを埋め込む要素。CSSセレクタで指定する

デザインをこだわった部分は以下の通りです。

  • はてなブログなどで表示されている、はてなスターのコードをほぼ再現
  • CSSは基本コピー
  • MutationObserver で、はてなスターのコンテナー(#hatena-star-container)配下のDOMの変更を検知して、画像のURLを差し替えたり、要素自体を差し替えたりする

<div id="hatena-star-container"></div>をはてなスターを表示したい場所に埋め込めばOKです。

Pocket

https://getpocket.com/publisher/button
でデザインを選んで、コードスニペットを取得できます。

<a data-pocket-label="pocket" data-pocket-count="vertical" class="pocket-btn" data-lang="en"></a>
<script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script>

あとは、このコードをボタンを表示したい場所に埋め込むだけで完了です。

Twitter

https://publish.twitter.com/?buttonType=TweetButton&widget=Button
で少し下にスクロールして Twitter Button > Share Button と選択すると、コードスニペットを取得できます。

<a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-show-count="false">Tweet</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

あとは、このコードをボタンを表示したい場所に埋め込むだけで完了です。

仕上がり

このブログでは、とりあえず、ソーシャルボタンを画面右下に常に表示することにしました。

はてなスターが付いた状態はこんな感じです。

スターが付くとボタンの位置がずれるのがいまいちですね。
特にモバイルでは邪魔になりそうなので、モバイルでははてなスターを表示するのはやめることにしました(このサイトの画面幅を狭めてみると確認で切ると思います)。

[参考] 最終的に埋め込んだソースコード

このサイト特有の設定も含まれるのであくまで参考までという感じですが、晒しておきます。
コードの半分以上ははてなスターの対応なので、そこを除けばスッキリしますw

<!-- share-links -->
<style type="text/css">
    #share-links {
        position: fixed;
        z-index: 2147483647;
        bottom: 5px;
        right: 5px;
        padding: 8px 8px 3px 8px;
        background-color: #ffffff8a;
        border-radius: 5px;
    }
    #share-links li {
        display: inline-flex;
        vertical-align: top;
    }
    #share-links ul {
        margin-bottom: 0;
        padding-left: 0;
        margin-left: 0;
    }
    .pocket-btn {
        line-height: 0;
    }
    @media (max-width: 600px) {
        #hatena-star-container {
            display: none;  
        }
    }
    #hatena-star-container {
        max-width: 200px;
        line-height: initial;
    }
    #hatena-star-color-pallet {
        display: none;
    }
    .hatena-star-add-button {
        margin: 0 !important;
    }
    .hatena-big-star-star-container {
        display: inline-block;
        position: relative;
        width: 20px;
        height: 20px;
        margin-left: 2px;
        vertical-align: middle;
        border-radius: 2px;
        overflow: hidden;
    }
    .hatena-star-user {
        position: absolute;
        width: 20px;
        height: 20px;
        z-index: 10;
        border-radius: 3px;
    }
    .hatena-star-star-refined {
        position: absolute;
        z-index: 11;
        top: 10px;
    }
</style>
<div id="share-links">
    <ul>
        <li>
            <a data-pocket-label="pocket" data-pocket-count="none" class="pocket-btn" data-lang="en"></a>
<script type="text/javascript">!function(d,i){if(!d.getElementById(i)){var j=d.createElement("script");j.id=i;j.src="https://widgets.getpocket.com/v1/j/btn.js?v=1";var w=d.getElementById(i);d.body.appendChild(j);}}(document,"pocket-btn-js");</script>
        </li>
        <li>
            <a href="https://twitter.com/share?ref_src=twsrc%5Etfw" class="twitter-share-button" data-show-count="false">Tweet</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
        </li>
        <li>
            <a href="https://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="basic-counter" title="このエントリーをはてなブックマークに追加"><img src="https://b.st-hatena.com/images/v4/public/entry-button/button-only@2x.png" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border: none;" /></a><script type="text/javascript" src="https://b.st-hatena.com/js/bookmark_button.js" charset="utf-8" async="async"></script>
        </li>
        <li>
            <div id="hatena-star-container"></div>
        </li>
    </ul>

    <script type="text/javascript" src="http://s.hatena.ne.jp/js/HatenaStar.js"></script>
    <script type="text/javascript">
        Hatena.Star.SiteConfig = {
            entryNodes: {
                'div.site-content': {
                    uri: 'window.location',
                    title: 'document.title',
                    container: 'div#hatena-star-container'
                }
            }
        };
        (() => {
            const observer = new MutationObserver((mutations) => {
                const addButtonEl = document.querySelector('.hatena-star-add-button');
                addButtonEl.src = 'https://cdn.blog.st-hatena.com/images/theme/star/hatena-star-add-button.svg';
                document.querySelectorAll(".hatena-star-star").forEach(starEl => {
                    if (!starEl.alt) return;
                    starEl.outerHTML = `<span class="hatena-big-star-star-container">
<img src="https://cdn.profile-image.st-hatena.com/users/${starEl.alt}/profile.png" class="hatena-star-user">
<img src="https://s.hatena.ne.jp/images/star.gif" alt="${starEl.alt}" class="hatena-star-star-refined">
        </span>`;
                });
            });
            const containerEl = document.querySelector('#hatena-star-container');
            observer.observe(containerEl, {childList: true, subtree: true});
        })();
    </script>
</div>