
特定環境下で衝突するんですよ (´・ω・`)
特定というと狭い範囲のように思いますが、広範です。
条件
- HTML5テンプレート を利用している
- 開閉プラグインが開閉トリガーに aタグ を用いている
- テンプレートにページ内スクロール(スムーススクロール)が導入されている
この条件が重なった時ですね。
挙動
- 開閉ボタンをクリックすると ページ最上部にスクロールしてしまう
この原因と対策についてです。
その前に、上記とは異なる挙動の場合もありますよね。初期状態で閉じているべきものが開いている(クリックも効かない) 逆もまた然り。こちらについてはまた別の原因ですので以下の記事を参照のこと。

FC2ブログプラグインの動作確認をお願いします【あなたのプラグインが動かない理由】
FC2ブログには プラグイン というのが用意されていますよね。 主にサイドメニュー部に簡単設置できて便利。 そして多種多様なものがあります。 中でも展開型プラグインは人気が高いような気がします。 アーカイブやコメントなどを 折りたたむ系 ですね。 公式プラグインというのはJS(Javascript じゃばすくりぷと)を極力使わない というのが制作理念のようです。 従って大変シンプルなものが多い。 一方、有志ユーザーさ...
変わってしまった aタグ の仕様
a(アンカー) というhtmlタグですが、html4からhtml5に移行するにあたり仕様が変更されています。
- name属性の廃止
- ダミーリンク(空リンク)の使い方変更
他にもありますが、今回の件に大きく関わる内容は上記2つです。
name属性廃止
html4時代の ページ内リンク というのは以下のようなことをしていたんですね
出発点
<a href="#jump">クリックすると移動します</a>
到達点
<a name="jump">ここが目的の位置です</a>
ページ遷移ではないですよ。ページ内移動 です。念のため。到達点の要素に対し、name属性を用いて目的地名称とします。それが旧式です。
現在ではどうするかというと
出発点
<a href="#jump">クリックすると移動します</a>
到達点
<div id="jump">ここが目的の位置です</div>
出発点の方の書き方は同じです。到達点の方が違います。html5では name属性が廃止 されているのと、到達点を a として設置する必要も無し になっているのですね (´・ω・`)
目的地名称はaタグのname属性を利用するのではなく、各要素のid名を利用するという形に変更されています。というのは、idを目的地名称とした場合にはaタグでのマークアップに限定される不都合が無いわけです。例えば「見出し」のマークアップは <hx>(xは1〜6までの数字) ですよね。じゃあそこへ飛ばすために見出しを <a> としてマークアップするの?ってことになります。それはどう考えてもセマンティックではないですよね。html5の理念というのは セマンティクス ですので、理に適っていない定義は軒並み廃止や変更が行われています。
というのがまずひとつ。
ダミーリンク(空リンク)の使い方も変更されている
空リンク(ページ遷移なし、移動なし)というのはどういう時に使うかというと、html4時代はそれこそ 開閉スイッチ に用いたり。別の言い方をすると プレイスホルダー (place holder)。
こんな感じ
<a href="#">クリックすると開閉します</a>
ページ遷移も移動もさせず、スイッチとして利用する。html5ではもうそういうことはしません。ダミーが必要な場合には
<a>クリックすると開閉します</a>
これでOK。
というよりもスイッチにaタグを用いる必要すらありません。<button> とかがありますから、わざわざ定義を曲げてまで <a> を使う理由はどこにもありません。
html4に於いては href属性が必須 でしたので、書かなきゃ仕方がなかったんですね。不要でも。その旧仕様が諸悪の根源です。
スムーススクロールとの衝突
ページ内で移動する際にスルスル〜っと動くアレです。何故このスムーススクロールが必要かというと、ページ内移動の際に何らかの動きが無いと、閲覧者は何が起こったかわかりにくいんですね。いきなりバッとページ最上部やら最下部にやら移動させるよりも、滑らかにページ全体が動く様子を見せることで「ページ内で移動している = ページ遷移ではない」というのがわかりやすいわけです。専門家の中には「ページ内移動自体するべきではない。」とする方も居て。
その理由は「ページは遷移するのが当たり前だ。していないとなると閲覧者が困惑する。」といった感じ。困惑させないためのスムーススクロールです。見た目にかっこいいとかそういうのももちろんありますが、それが第一目的ではありません。
スムーススクロールを実装するにあたり、JSコード内に通常は以下のような記述が含まれます。
a[href^="#"]
緑の #
ハッシュ あるいは フラグメント と読みますが、この記述の意味というのは「id名がついていたら」です。html5の到達点というのは要素のidで示しますが、id名というのはコードを書いた人間が任意でつけますので特定ができません。ですから「id名への移動(ページ内移動)がある場合は全て」という形にせざるを得ないんです。
#hoge
かもしれないし、
#top
かもしれないし、
#bottom
かもしれない。それはわかりませんが、以下のようにフラグメントへの移動が示されたら
<a href="#hoge">クリック</a>
スムーススクロールを起動させてください、という意味です。で、既におわかりの通り、html4時代の開閉プラグインというのは大抵
<a href="#">クリック</a>
こうしてaタグをトリガーにし、必須属性のhrefの値を「空」のつもりで#
これが スムーススクロールの動作条件に含まれてしまう わけです。
対処法
「どうして」の原因がおわかり頂けたと思いますので、今度は「どうするか」の対処について。
スムーススクロールを削除する
ページTOPやらのボタンなどそもそも要らないんだ、という方はですね、scriptを削除してください。scriptを削除しても移動自体は行なえます。行えはしますが、押した瞬間にバっと移動してしまいますので味気ないのと(ry
この処理はテンプレート側で行います。
スムーススクロール対象を限定的にする
テンプレート製作者次第ですが、大抵の場合にはみなさんが記事内で使用できるようにコードが組まれています。正しいhtmlを書きさえすれば記事内でスムーススクロールを利用することが可能です。JSを書く必要はありません。「記事内で使うことなんて絶対にない!」と言い切れる方は、対象要素を限定してください。ページTOPへのスムーススクロールだけが必要ならば
$('a[href^="#"]')
緑の部位を
$('a[href^="#top"]')
と、こんな風に特定id名を入れます。「#top と書け」という意味ではないですよ。top の部分は移動対象になるid名を入れてください。それはテンプレート毎にまちまちですからここで「こう書け」とは言えません。各々ちゃんと調べて入れる、と。移動対象が複数あるならば
$('a[href^="#abc"],a[href^="#xyz"]')
こうしてカンマ区切りで指定。この処理はテンプレート側で行います。
対象プラグインをスムーススクロール除外指定
対象プラグインの衝突しているaタグにid名をつけます。はじめから付いている場合にはそれをそのまま利用します。
例)
<a href="#" title="OPEN" onclick="xxxxx;return false;">クリック</a>
xxxxxの部位は不特定の文字列です。
大体はこんな感じになっているのではないかと思います。
上記内容、現時点ではid名がありませんので追加します。
<a id="hoge" href="#" title="OPEN" onclick="xxxxx;return false;">クリック</a>
この作業はプラグイン側で行います。その上でテンプレート内のスムーススクロールのコードを
$('a[href^="#"]:not(#hoge)')
こうして除外する。対象が複数あるのならば
$('a[href^="#"]:not(#hoge):not(#hoge2)')
こうして :not() で繋げます。id名は 単一 指定しかできませんので対象が複数あるならばそれぞれにid名を付けてください。idでなくclassにすれば一括指定はできますが、ここでは強制力の強いid名をおすすめします。
この処理はプラグイン側 + テンプレート側 双方の作業です。
まとめ
簡易的な修正は上にまとめた通りです。私のおすすめはどれかというと、どれも該当しません。最善策は html5に準拠したものを使う ことです。
There are no comments yet.