jQueryで横並びメニューを均等配置。でもWebフォントに足元すくわれた。

今回の趣旨はWebフォントによるトラブルですが、jQueryを使った均等配置メニューの参考にもなるかと思ったので、顛末をすべて掲載。

不具合発生までの経緯

  • jQueryで横方向に均等に配置されたテキストメニューをつくる。
  • CSSではなくjQueryを使う理由は、テキスト内容やフォントサイズが変更しても崩れないようにするため。
  • なぜか初回読み込み時のみメニューの位置がずれる(2回目以降は問題なし)

まずは不具合のないメニューを確認

やりたいこと

  • 両端を領域幅に合わせる(左右余白を「0」にする)
  • メニューを均等に配置する(間隔を揃える)
  • フォントサイズが変わってもレイアウトを維持
  • メニュー名が変更されてもレイアウトを維持

※下のメニューが、上に書かれている「やりたいこと」通りに見えないという方がいましたら、ご一報くださいませ。

メニュー数が5つの場合

メニュー数が4つの場合

ソース

html

メニュー数5の場合です。

<ul class="dummy_menu clearfix">
	<li><a href="#">りんご</a></li>
	<li><a href="#">パイナップル</a></li>
	<li><a href="#">グレープフルーツ</a></li>
	<li><a href="#">スイカ</a></li>
	<li><a href="#">メロン</a></li>
</ul>

CSS

ul.dummy_menu {
	margin: 0 0 25px;
	padding: 1em 0;
	list-style: none;
	border-top: 1px dotted #ccc;
	border-bottom: 1px dotted #ccc;
}
ul.dummy_menu li {
	float: left;
	padding: 0.5em;
	border: 1px solid #ccc;
	background-color: #f8f8f8;
}
//clearfixは省略しています

jQUeryスクリプト

$(function(){
	var liTotalWidth = 0;
	var marginR = 0;
	var li_menu = $("ul.dummy_menu li");

	li_menu.each(function() {
		liTotalWidth += $(this).outerWidth();
	});
	marginR = Math.floor( ( $("ul.dummy_menu").width() - liTotalWidth ) / ( li_menu.length - 1 ) );
	li_menu.not(":last-child").css({
		marginRight: marginR + 'px'
	});
});

上記の記述で、このページでは何も問題なく表示されています。

なのに、不具合が生じたサイトではなぜかブラウザでの初回アクセス時のみメニューの間隔が狭く表示されます。(左側に余白が空く。)で、「F5」(Macなら「command+R」)で再読み込みすると正しく表示され、その後は何も問題ない。

何が問題だったのか

スクリプトは正しい?問題は別にあり

これ、最初はズレが発生していること自体まったく気づかず。だってページデータがブラウザにキャッシュされた状態では問題が起こらないので。(開発中はChromeで表示を確認)

で、Firefoxでチェックすると、「あれ? メニューがずれてる?」

で、「F5」を押したらちゃんと表示され、その後はずっと問題なし。「気のせいか…」

で、次にIEでチェック。「あれ?メニューがずれてる?」

で、「F5」を押したらちゃんと表示され、その後はずっと問題なし。「気のせいか…」

いやいや、気のせいじゃないよねコレ!

で、Chromeでキャッシュを削除して再度確認すると…、ズレている…。

CSS、スクリプトファイルの読み込み順をチェック・変更

スクリプトを順番にデバッグしてわかったのは、ブラウザにキャッシュされる前と後とでは、メニュー幅(li.outerWidth())の数値が異なっていること。
ということは、CSSが読み込まれる前にスクリプトが実行されている可能性が高いです。でも、CSSが読み込まれる前だとしたら、もっと色々と表示が崩れるはずです。ここで非常に悩みました。
で、WordpressのCSSファイルやスクリプトの読み込み順を色々と変えてみました。jsファイルをbody終了タグ直前に変更してみたり。でもダメ。一向に症状が改善されません。

そこで、jQueryスクリプトをすべてのページデータを読み込んでから実行するよう、以下に変更。

//変更前
$(function(){
	//実行する内容
});

//変更後
$(window).load(function() {
	//実行する内容
});

すると正しく表示されましたよ。やはり先に読み込まれるべきものが読み込まれていなかったということです。
これで問題解決と行きたいところですが、今度はjQueryスクリプトの実行が最後に回されたことにより、実行前後でやはり表示がズレるんです…。崩れた状態のメニューがまず見えて、1秒後くらいにビヨッと動く…。最初の状態よりも気持ち悪い。

うーん。
一瞬、悪魔のささやきが頭をよぎります。
「ブラウザにキャッシュがない状態のときだけなんだから、気にしなくてもいいよ…。 無視、無視。」

でも、これお客さんのサイトだし、自分としてもこのまま原因不明ではスッキリしない。
それからしばらく考えて、ふと、今回はこれまで使ったことのないものを使っていることに気づきました。
Webフォント

原因はWebフォント。読み込みに時間がかかっていた。

今回依頼のサイトでは、フォントが指定されていました。GoogleフォントなどのCDNにはないフォントだったので(有償ならあったかな?)、ライセンスに基づきWordpress内にフォントファイルを置いて指定することに。これはbody要素に対して指定しています。ひょっとして原因はこれかと思い、試しにfont-familyからWebフォントを外してみると・・・。

無問題!!

長かった。これがわかるまでにどれだけ時間を費やしたことか。
で、原因がわかったところで、さてどうしましょうか。Webフォントの使用をやめるわけにはいきません。クライアントのデザイン指示なので。
ユーザーに初回だけ泣いてもらうか(でもクライアントに気づかれたらきっと修正指示がくるよね)。
誰かもっともスマートな方法を教えてください。

Wordpress, 備忘録 | , |