はてなブログ用テーマチェンジャー(デモサイト公開用)

あまり(ほとんど)役に立たないものを作りました(笑)。

はてなブログのテーマを公開する際にはデモサイトがあったほうがわかりやすいのですが、たくさんテーマを公開しますとサイトが足りなくなります。そんな時にテーマチェンジャーがあるといいなあと思い作ってみました。

ですので、通常のサイトでは役に立つものではありません。それにまだテーマをたくさん公開しているわけではありません(笑)。



デモサイト

ausnichts.hateblo.jp

テーマストア」や「はてなブログ多機能テーマ imz-basic を公開します」の記事で公開しているテーマのデモサイトに、サンプルとしてかなり昔に作ったテーマとのテーマチェンジャーをつけています。


f:id:ausnichts:20190725164136j:plain

キャプチャです。画面右にテーマ切り替えボタンが見えます。


はてなブログのテーマの仕組み

作ってしまえば簡単なものですが、結構手間取りました。と言いますのは...


はてなブログのテーマは、デザイン > カスタマイズ > デザインCSS に CSS を入れておけば外部ファイルとして <head></head> 内にリンクしてくれます。

テーマストアでテーマを選択しても、デザインCSSに直書きしても同じです。テーマストアのテーマを選択した場合は、

/* <system section="theme" selected="smooth"> */
@import "/css/theme/smooth/smooth.css";
/* </system> */

が入りインポートされるだけです。その CSS のフルパスは https://blog.hatena.ne.jp/css/theme/smooth/smooth.css です。


ブログには、その CSSファイルが直接リンクされるわけではなく、別ファイルとして保存されそれをリンクするようになっています。スタイルを追加する場合もあるわけですから当然ですね。

このブログでは、

 <link rel="stylesheet" type="text/css" href="https://blog.hatena.ne.jp/-/blog_style/12704346814673864141/d71e43c5e77f4d4661905466522ceebf85c45385"/>

こうなっています。


で、テーマチェンジャーを作るには、このリンク先を変えればいいだろうと、テスト用に2,3テーマを入れ替えてリンク先を切り替えてみたんですが、あれ? あれ? あれ? と、切り替えてもテーマが変わらない(ときがある)のです。


悩むことしばし(ではなく随分)、このリンク先は静的ファイルではないようです。仕組みまでは調べていませんが、どうやら動的にファイルがつくられるようです。間違っていたらすみません。


テーマチェンジャー

ということで、結局、はてなブログのリンク先を変更する方法はあきらめ、Githubページを使うことにしました。

切り替えボタン

デザイン > カスタマイズ > フッタ に入れます。

カスタムデータ属性を使い、css, js ファイル名と javascript を使うかどうかを指定します。

<div id="themeChanger">
    <div class="tc-child" data-name="テーマ名" data-js="yes"><span>テーマ名</span></div>
    <div class="tc-child" data-name="テーマ名" data-js="no"><span>テーマ名</span></div>
</div>


Javascript

デザイン > カスタマイズ > フッタ に入れます。

sessionStorage を使っている理由はテーマのリセットです。CSS ファイルのリンク先を変えるだけですので、ひとつのテーマを選択しますとそのスタイルが残ってしまいます。body{ all: initial } を試してみたのですが、これをやりますとはてなブログのベーススタイルまでリセットされてしまいます。

(2019.8.7)キャッシュをクリアするために読み込むファイル名にクエリを追加しました。


(function(){
    function setCssFile(theme, js){
        const fresh = sessionStorage.getItem('fresh');
        if(fresh === 'false') location.reload(true);

        const oldTheme = sessionStorage.getItem('themeChanger');
        if(oldTheme !== null) theme = oldTheme;

        const head = document.getElementsByTagName('head')[0];
        const query = '?' + Date.now();
        const url =  'https://アカウント名.github.io/css/' + theme + '.css' + query;
        const link = document.createElement('link');
        link.setAttribute('rel', 'stylesheet');
        link.setAttribute('type', 'text/css');
        link.setAttribute('href', url);
        head.appendChild(link);

        if(js === 'yes'){
            const bottom = document.getElementById('bottom-editarea');
            const src =  'https://アカウント名.github.io/js/' + theme + '.min.js' + query;
            const script = document.createElement('script');
            script.setAttribute('type', 'text/javascript');
            script.setAttribute('src', src);
            bottom.appendChild(script);
        }
        sessionStorage.setItem('fresh', false);
    }
    
    sessionStorage.setItem('fresh', true);
    const tcItems = document.getElementById('themeChanger').children;
    Array.prototype.forEach.call(tcItems, function(item){
        const theme = item.getAttribute('data-name');
        const js = item.getAttribute('data-js');
        item.addEventListener('click', function(){
            sessionStorage.setItem('themeChanger', theme);
            setCssFile(theme, js);
        }, false);
    });
    const theme = tcItems[0].getAttribute('data-name');
    const js = tcItems[0].getAttribute('data-js');
    const bg = tcItems[0].getAttribute('data-bg');
    setCssFile(theme, js);
}());


サンプルCSS

デザイン > カスタマイズ > デザインCSS に入れます。


#themeChanger {
    position: fixed;
    top: 70px;
    right: 0;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
        -ms-flex-direction: column;
            flex-direction: column;
    z-index: 9999;
}

#themeChanger .tc-child {
    margin-bottom: 10px;
    width: 70px;
    height: 70px;
    font-size: 12px;
    color: #ffffff;
    font-weight: bold;
    text-align: center;
    border-radius: 3px;
    border: 1px solid goldenrod;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
        -ms-flex-align: center;
            align-items: center;
    -webkit-box-pack: center;
        -ms-flex-pack: center;
            justify-content: center;
    cursor: pointer;
}

#themeChanger .tc-child:nth-child(1) {
    background-color: #2196f3;
}

#themeChanger .tc-child:nth-child(2) {
    background-color: #f092e0;
}


ライセンス等

ご使用の場合は以下の注意事項をお守りください。

  • ライセンスは IMUZA.com にあります。
  • 当記事の Javascript を使用していただくのは商用をのぞいて自由ですが、転載は禁止です。
  • 当記事の CSS への改変、公開は自由です。
  • 特別問題が発生することはありませんが自己責任でお使いください。
    問題が発生した場合は削除すればもとに戻ります。
  • お問い合わせ、バグの報告、仕様変更のご要望等は Contact Us までお願いします。