くぜのメモ

メモのように色々なことを書いていく雑記ブログ

【はてなブログ】サイドバーのコンテンツをスクロールに合わせて追従させる方法【脱jQuery】

f:id:CXE:20220331105001p:plain

こんにちは、くぜです。

今回は、はてなブログにおいて、サイドバーに配置したコンテンツをスクロールに合わせて追従させる方法を、備忘録がてら書いていこうと思います。

今回紹介する方法は、デザインCSSとフッタにコードを記述するのみで完了します。

本ブログでは、紹介する方法を用いて、サイドバーの最後尾に配置した広告をスクロールに合わせて追従するように設定しているので、使用感を見たい方は確認してみてください。

※ ブログで使用しているデザインテーマなど、ブログの設定によっては正常に動作しない可能性があります。本記事の内容は、デザインテーマ『Smooth』での動作を確認しています。

参考:はてなブログのサイドバーにスクロールに追従するコンテンツを置く - めも

① デザインCSSにコードを追記

デザインカスタマイズデザインCSS と進んでいき、以下のコードを追記します。

以下のコードは最後尾のコンテンツを指定していますが、最後尾から2番目のコンテンツを指定したい場合には、.hatena-module:nth-last-child(2)などと指定すればOKです。

※ 2022/8/24 追記 はてなブログの仕様に合わせてtopを10px→40pxに変更

/* サイドバーコンテンツ追従 */
.hatena-module:last-of-type {
    position: sticky;
    top: 40px;
}
  遷移方法

ダッシュボードで『デザイン』を選択

カスタマイズ』を選択し、『デザインCSS』に移動し、コードを追記
  処理説明

.hatena-module:last-of-typeで、サイドバーにある各コンテンツの中で最後尾のコンテンツを指定しています。

positionの値にstickyを指定した要素は、通常の位置に配置されますが、スクロール等でtop, right, bottom, leftに指定した位置に達したとき、その位置に名前の通り「粘着」するような形で配置されます。

今回でいえばtop: 10px;と指定しているため、コンテンツの上端が、ウインドウの上端から10pxの箇所に達したときにその場所で固定配置されます。

② フッタにコードを追記

デザインカスタマイズフッタ と進んでいき、以下のコードを追記します。

正直、フッタでなくても、ヘッダや記事など、コードを認識できる場所であればどこでもいい。動作確認はしていないが。

<!-- サイドバーコンテンツ追従 -->
<script>
    (window.onload = function() {
        var mainHeight = document.getElementById('main').offsetHeight; 
        var box2Height = document.getElementById('box2').offsetHeight;
        if (mainHeight == box2Height) {
            var box2Inner = document.getElementById('box2-inner');
            box2Inner.style.height = box2Height - 100 + 'px';
        }
    })();
</script>
  遷移方法

ダッシュボードで『デザイン』を選択

f:id:CXE:20220331163242p:plain

カスタマイズ』を選択、『フッタ』に移動し、コードを追記
  処理説明

position: stickyで指定した要素は、その親要素内でしか機能しません

しかし、親要素box2-innerの高さは、サイドバーの最前列コンテンツの上端から最後尾コンテンツの下端までとなっており、スクロールしても追従させる余白が無い状態です。

ですので、記事が十分に長く、コンテンツを追従させる余裕がある場合、box2-innerの高さをサイドバーbox2の高さと同じ高さに設定し、追従可能にさせます。

まず、DOM要素が読み込まれた後に本処理が実行されるよう、window.onloadを使用します。

次に、document.getElementById('main').offsetHeightで記事の高さ、document.getElementById('box2').offsetHeightでサイドバーの高さを取得します。

この記事の高さ、サイドバーの高さですが、基本的には同じ値になります。しかし、記事の文量が少なかった場合、サイドバーの高さが記事の高さを上回る場合があります。

この時は処理を回す必要がないので、if文を使って、以降は記事の高さとサイドバーの高さが一致する場合のみ処理させます。

あとは、box2-innerbox2の高さを代入するだけです。

この時、box2の高さを-100していますが、これはbox2paddingが設定されているためです。

そのまま高さを代入してしまうと、記事の高さよりサイドバーの高さがpadding値の2倍分長くなってしまいます。

対応しようかと思いましたが、1emが設定されていて計算が面倒なので適当に-100しています。

上手いやり方をご存じの方はコメントなどで教えていただけると幸いです。

まとめ

以上、『サイドバーのコンテンツを追従させる方法』でした!

ちなみにですが、<details>タグを使用して折りたたみ要素を組み込むと、開閉状態の変化に対応できず、コンテンツの追従が途中で止まります。
どうやら<details>タグはtoggleイベントに対応しているようなので、フッタに処理を加えれば対応可能っぽいです。
時間があるときに対応します。

最後に、本記事の内容ですが、コピペなどは自由にしていただいて大丈夫です。また、記事として投稿する場合は、本記事のリンクを貼っていただけると助かります。

以上、ここまで読んでいただき、ありがとうございました!