いわゆるシングルページナビゲーションみたいなやつ(はてなブログ用) (2021/08/12 ver3.4.1)
できること
- サイドバーに目次を設置
- スクロールに合わせて追尾
- 現在位置の背景色変更
- リンク先へのスムーズスクロール
- ウィンドウサイズ変更に合わせてサイズ変更
- 記事ページ以外でもページ内の記事一覧などを表示
動作環境
- サイドバーが横に表示されるテーマ
- 親要素に
transform
やoverflow:hidden
がないテーマ
動作確認はPC版のChrome、FireFox、Edge、IE11で行っています。
※設定によってはスマホやタブレットでも動きますが基本的にPC向けです。
※追記(2021/08/12)
はてなブログの推奨ブラウザからIE11が削除されたため、本スクリプトもver3.4.1以降はIE11での動作確認はしません。
前バージョンからの主な変更点
- ウィンドウサイズ変更に対応
- 使えるテーマが増えた
- HTML構造変更(
<div class="sectionList"></div>
削除など) - CSSのidとクラス名変更(
#sectionListSide → #stoc
、.current → .active
など)
他にもjQuery使うのをやめたりと変更点が多いです。
インストール
念のため追加する前の設定は保存しておきましょう。
テスト用の非公開ブログを作ってそっちで試すといいかも。
HTML
デザイン設定の[カスタマイズ]-[サイドバー]-[モジュールを追加]-[HTML]に貼り付ける。
タイトルはスクリプトが読み込まれた段階でスクリプト側で設定したものに置き換えられます。
JavaScript
デザイン設定の[カスタマイズ]-[フッタ]に追加する。
(上のHTMLの後に追記してもたぶん動きます)
これを開いて全てコピー → sidebar_toc_footer_minify(Raw)
見づらいですが圧縮前のもデバッグ用にどうぞ → sidebar_toc_footer(Raw)
CSS
デザイン設定の[カスタマイズ]-[デザインCSS]に追加する。
※追記(2019/04/01)
前バージョンのCSSを流用する場合、一部のidとクラス名が変更されたり書き方が変わっているので注意(#sectionListSide → #stoc
、.current → .active
など)。
文字色(2018/04/22追記)
デフォルトではページに設定されたリンクの色が使われますが、変更したい場合はCSSに下記を追加します。
上のCSSでコメントアウト(/*~*/
)されている部分を編集してもOK。
#stoc a { color: #カラーコード; } /* マウスカーソルをあわせた時 */ #stoc:not(.touch) a:hover { color: #カラーコード; } /* 現在位置 */ #stoc .active { color: #カラーコード; } /* 訪問済みのリンクの色(一色だけにしたい場合は指定しない ※テーマによる) */ #stoc a:visited { color: #カラーコード; }
設定について
JavaScriptの冒頭部分を変更することである程度動作を変えられます。そのままでも動きますがテーマや好みに応じて変更してください。
true
はオン、false
はオフみたいな意味で、目次タイトル以外の部分は全て半角で書きます。
ここで説明するもの以外についてはこちら→ オプション
メディアクエリ(重要)
変数名 | デフォルト |
---|---|
MATCH_MEDIA |
false |
MEDIA_QUERY_SIDEBAR |
'(min-width: 768px)' |
目次がスクロールに追尾してこない・現在位置の背景色が変更されないなどの場合はこの設定を見直してみてください。
デフォルトではサイドバー要素が横に表示されているかを#box2
要素のfloat
プロパティがnone
かどうかで判定しています。
(正確にはgetComputedStyle(document.getElementById('box2')).cssFloat
の結果がnone
かどうか。float
がない場合もnone
が返される)
多くのテーマはそのままで動きますが、Boilerplateを元に作られたテーマなどはfloat
のかわりにメディアクエリが使われていて判別が難しいので、直接サイドバーが表示されるページの横幅を設定します。
MATCH_MEDIA
をtrue
にして、MEDIA_QUERY_SIDEBAR
にサイドバーが表示されるページ幅の条件などを書きます。
MEDIA_QUERY_SIDEBAR
にデフォルトで入ってる'(min-width: 768px)'
だと「ページの横幅が768px以上」ならサイドバーが表示されている(追尾する)という意味になります。
条件の調べ方(2019/04/08追記)
ページの横幅がいくつならサイドバーが表示されるかはテーマによって違うので、以下の方法で調べた数値を〇〇の部分に入れます。
const MATCH_MEDIA = true; const MEDIA_QUERY_SIDEBAR = '(min-width: 〇〇px)';
例1:簡単な調べ方
- ブログの記事ページを開く
- F12を押すと出るデベロッパー(開発者)ツールを開く
- コンソール(Console)の入力欄(
>
や>>
の所)に下のコードを貼り付けて実行(Enter) - ウィンドウ幅を調整してサイドバーが表示されるギリギリのサイズの時、コンソールに表示されている数値
window.addEventListener('resize', function(){console.log(window.innerWidth)})
(Chromeはデベロッパーツールを開くだけでもウィンドウ幅変更時に右上にサイズが表示されます)
例2:CSSを調べる方法
(#box2
にメディアクエリが指定されている場合)
- ブログの記事ページを開く
- ChromeなどのブラウザでF12を押すと出るデベロッパーツールを開く
- サイドバー要素(
#box2
)を選択
body > #container > #container-inner > #content > #content-inner > #box2
- ウィンドウ幅をサイドバーが表示されない状態まで調整(必要以上に小さくしない)
- Stylesペインに④の
@media ~
があればmax-width
またはmin-width
を確認
今回の場合は'(max-width: 1138px)'
なので「ページの横幅が1138px以下」で適用されるCSSが書いてある。
つまりサイドバーが表示されるのは「ページの横幅が1139px以上」のはずなので〇〇には1139
を入れる。
目次を表示するページ
記事ページでは普通に見出し一覧を表示しますが、トップページやアーカイブページでは記事タイトル一覧を目次として表示できます。
デフォルトでトップページやアーカイブページでも表示するように設定されていますが、必要無い場合はpage-index
とpage-archive
のdisplay
をtrue
からfalse
に変更してください。
{ class : 'page-index', title : 'このページの記事一覧', listPage : true, display : false // ここをtrueからfalseに }, { class : 'page-archive', title : 'このページの記事一覧', listPage : true, display : false // ここをtrueからfalseに },
設定を変えればタイトルの変更やPro機能の固定ページでも表示できます。
詳しくはこちら→ PAGES options
表示する見出しタグ
変数名 | デフォルト |
---|---|
HEADLINE_QUERY |
['h3', 'h4', 'h5'] |
目次に表示したい見出しタグを指定します。数字が小さい順に書いてください。
固定時の余白
変数名 | デフォルト |
---|---|
MARGIN_TOP |
10 |
MARGIN_BOTTOM |
0 |
目次モジュールが固定(追尾)される時の上下の余白を指定できます。
グローバルメニュー
変数名 | デフォルト |
---|---|
GLOBAL_HEADER |
['#globalheader-container'] |
- 追尾開始位置を正しく取得するために、ヘッダーメニュー・グローバルメニューなどと呼ばれる常時表示・追尾型のメニュー(上に表示されるもの)の
id
かclass
を指定します id
の場合は#
、class
の場合は.
を先頭に書いてくださいclass
を指定して複数の要素が見つかった場合でも先頭の要素だけを対象にします- 複数指定する場合は
['#globalheader-container', '.global-menu']
のようにコンマで区切って書きます - Pro版でヘッダを非表示にしている場合はデフォルトの
'globalheader-container'
は消しても大丈夫ですが[]
は残してください - 目次と重なる時は
MARGIN_TOP
を調整します
見出し位置などの更新(2018/05/03追記)
変数名 | デフォルト |
---|---|
CLICK_UPDATE |
[] |
CLICK_UPDATE_DELAY |
500 |
現在位置表示用の見出し位置や目次の追尾開始位置などはロードが終わった時やウィンドウサイズ変更後に取得していますが、他の要因で高さが変わるとずれてしまいます。
このオプションで指定された要素をクリックすると見出し位置などの更新が行われるので、クリックによる目次の開閉などで高さが変わってもずれないように出来ます。
CLICK_UPDATE
に指定する要素の書き方は上のGLOBAL_HEADER
と同じ
ただしclass
を指定した場合は見つかった全ての要素が対象になります。CLICK_UPDATE_DELAY
は要素クリック後の更新を遅らせる時間
アニメーションの時間などを考慮して調整してください。
たとえば['.archive-module-hide-button', '.archive-module-show-button']
と指定すると、サイドバーの「月別アーカイブ」モジュールの開閉ボタンをクリックした後に更新され、目次の追尾開始位置のずれを防げます。
スムーズスクロール
変数名 | デフォルト |
---|---|
SCROLL_TIME |
400 |
SCROLL_TIME_TOUCH |
0 |
- スムーズスクロールにかける時間をミリ秒で指定できます(
TOUCH
が付いてる方はタッチデバイスでのスクロール時間) - 0にするとスムーズスクロールはオフになります
HTML構造
色が薄い所ははてなブログ側で用意される部分です。
(nav#stoc
はインストール時に貼り付けたHTML)
追尾中#stoc-module
に付与されるクラスの条件
tracking
ウィンドウかページに固定している時fixed
ウィンドウに固定している時absolute
ページに固定(下までスクロール)している時
fade-in
他のサイドバーモジュールより上に設置していて追尾開始した時
仕様と注意点
- 見出しが設定値より少ない・表示する設定にしていないページの時はモジュール全体を非表示にします
- 目次記法による目次が表示されていない時のページ内リンクは
section0, section1...
になります - ※追記(2019/08/08) 目次記法のリンクにもスムーズスクロールや履歴の設定が適用されます
- ※目次を表示しない設定のページでは適用されません
- 目次やメニューの開閉などでページの高さが後から変わったりすると現在位置表示はずれます
- ※追記(2018/05/03)
CLICK_UPDATE
オプションである程度対応可能 解説↑
- ※追記(2018/05/03)
- 沢山サイドバーモジュールを設置していると見づらいので置き過ぎには注意しましょう
タッチデバイスでの動作
レスポンシブデザインモードやPro機能、「PC版サイト表示」などをしない限りあまり関係ない話。
※追記(2019/08/08) タッチデバイスで非表示にする設定を追加TOUCH_DEVICE_DISABLE
スマホなどタッチデバイスでのスクロール処理はPCと違うので追尾が不自然になったりします。これを解決するためにタッチデバイスの時はposition:sticky
(IE11未対応)を使っているのですが、そのために以下の処理が入ります↓
#stoc-module
と#stoc
に.touch
クラスを追加- ブラウザが
position:sticky
に対応していれば#stoc-module
に.sticky
クラスを追加- サイドバーモジュールの親要素
#box2-inner
の高さを記事部分#main-inner
の高さと合わせる
- サイドバーモジュールの親要素
#box2-inner
の高さを変更した影響でテーマによっては見た目が変になりますが仕様です。
h2タグを使用する場合(2019/11/11追記)
はてなブログでh2タグを使用する場合、h2タグが使用されていないページで見た目を揃えるために見出しタグを書き換えるスクリプト(h3→h2
, h4→h3
...のように)を使う場合があります。
このスクリプトと追尾する目次スクリプトを同時に使用すると、最初に取得した見出し要素が後から書き換えられ、見出し位置の取得ができなくなってしまいます。
なのでDELAY_GET_DOM
オプションをオンにして書き換えスクリプトが実行されたあとに見出し要素を取得することでこの問題を回避できます。
変数名 | 説明 |
---|---|
DELAY_GET_DOM |
見出しなどを取得するタイミングをHTMLが読み込まれたあとにする |
簡易なスクリプトの処理順
- HTMLを順番に読み込み
- 読み込まれたスクリプトが順番に実行される
- [追尾目次] 見出し要素などを取得
- HTMLの読み込みと解析が完了(DOMContentLoadedイベント)
- 画像など全ての読み込みが完了(loadイベント)
こんなときは
デザイン・色が合わない
テーマによっては追尾中に背景色がなくなるなどの症状が出ます。
簡易的ですが以下の公式テーマ向けのCSS例(記事執筆時点)→ カスタマイズ例
- Aero
- Afternoon
- ヨミカキ by kanahei
- Popcorn by カタノトモコ
- Report
- レトロポップ
- Skull wings
- Solid
- Terminal
- Venetia
目次の上下に白いグラデーションが表示される
ページの縦幅よりも目次が大きい時にスクロールバーとさらにスクロール可能かを分かりやすくするためのオプション機能(SCROLL_SHADOW
)があるんですが、
デフォルトでは白い背景色に合うように設定されているのでテーマに合わせて変更する必要があります。
[デザインCSS]に追加した以下の部分を
/* Shadows */
の下に2つあるrgba(0,0,0,.17)
(透明度のある黒)を表示したい色/* Shadow covers */
の下に2つある#fff
(真っ白)を背景色と同じ色
にそれぞれ設定します
/* sidebar_toc.css */ #stoc.shadow { /* Shadows */ background: radial-gradient(farthest-side at top, rgba(0,0,0,.17), transparent) top / 100% 11px, radial-gradient(farthest-side at bottom, rgba(0,0,0,.17), transparent) bottom / 100% 11px; } #stoc.shadow > ol { /* Shadow covers */ background: linear-gradient(#fff 30%, transparent) top / 100% 40px, linear-gradient(transparent, #fff 70%) bottom / 100% 40px; }
この表示自体いらない場合は設定部分のSCROLL_SHADOW
をfalse
にしてください。
フッタに空の要素が表示される
フッタにスクリプトを書いた影響でテーマによっては空の#bottom-editarea
要素が表示されます。非表示にしたい場合は[デザインCSS]に以下を追加してください。
#bottom-editarea { display: none; }
フッタに他の要素がある場合動作がおかしくなるかも知れないので注意。
もしくはフッタではなくHTMLを書いた場所にスクリプトを追記するようにしても動きます。たぶん。
追尾する位置になると画面外に消える
親要素にアニメーションなどでtransform
が使われているとposition:fixed
が上手く動かなくなり表示できません。
position:sticky
を使うモードにすると治る可能性があります(F_STICKY_MODE
)。
親要素にoverflow:hidden
があると動かないので注意。
なにかいい方法があるかも知れませんが基本的に親要素にtransform
は使用しないでください。
あとがき
まさかの大型バージョンアップ3回目。もうここまで大きな更新はしない(はず)。
なるべく分かりやすいように作りたかったけど分かりづらいですね申し訳ない。各自頑張って…。
正直標準の公式テーマ対応するだけで力尽きたので他のテーマだとおかしいかも。
要望やバグ報告はコメント欄かGoogleフォームかTwitterへ。
ただし対応できるかは分からないのであまり期待せずにどうぞ。