共通ナビゲーションをインクルードする時の話
Webサイトのヘッダやナビゲーションで、現在表示しているページに対応する部分だけ色を変えたり画像を変えたりすることがある。たとえばこんな風にクラスを用いたり。
<nav>
<ul>
<li><a href="#">Top</a></li>
<li class="current"><a href="#">About</a></li>
<li><a href="#">Service</a></li>
<li><a href="#">Company</a></li>
<li><a href="#">Inquiry</a></li>
</ul>
</nav>
nav ul li a {
color: #333333;
}
nav ul li.current a,
nav ul li a:hover {
text-decoration: underline;
color: #FF0000;
}
上記のように対応できると何も問題ないのだが、共通パーツとしてインクルードした時にクラスを置くことができないケースがある。変数を渡したりサーバサイドで何かしら判定すればできるが、そう簡単にはいかないのが世の常である。
もちろんJSを使ってURLを見れば大概のケースは解決可能であるが、それでも大変なケースがある。上記ナビゲーションを例に出すと、Company以下に複数ページがある場合、company/ディレクトリ以下にAboutページがある場合、Service以下が複雑なディレクトリ構成になっている場合、など。具体的でないのでイメージしづらいかもしれないが、とにかく大変なことがあるのである。
解決策
こんな時、たとえば各ページのbodyタグに「現在地」を示す情報を置けば、CSSだけでスマートに解決できる。bodyタグでなくても、ナビゲーションを内包するコンテナ系のブロックであれば何でもよい。
<body data-current-nav="top">
<body data-current-nav="about">
<body data-current-nav="company">
<body data-current-nav="service">
<body data-current-nav="inquiry">
nav ul li a {
color: #333333;
}
[data-current-nav="top"] nav ul li:nth-child(1) a,
[data-current-nav="about"] nav ul li:nth-child(2) a,
[data-current-nav="company"] nav ul li:nth-child(3) a,
[data-current-nav="service"] nav ul li:nth-child(4) a,
[data-current-nav="inquiry"] nav ul li:nth-child(5) a,
nav ul li a:hover {
text-decoration: underline;
color: #FF0000;
}
ナビゲーションが頻繁に変更されるような場合は、:nth-childじゃなくて<li/>にクラスを割り当てるのがいいと思う。
[data-current-nav="top"] nav ul li.top a,
[data-current-nav="about"] nav ul li.about a,
...
利点として、
- JSやサーバサイドのスクリプトが必要ない。
- スクリプトが必要ないため、プログラマでなくても開発可能。
- ナビゲーションに対応するページが複数ある場合でも問題ない。
- 複雑なページ構成、ディレクトリ構成に依存しない。
- ナビゲーションが複数ある場合(PC/SPで別々、など)でも、CSSを追加するだけ。
CSSが冗長!見にくい!
CSSがごちゃごちゃするのが嫌な人にも、上記のHTML設計はオススメ。というのも、JSで記述したい場合でも、bodyタグのdata属性を取得するだけで解決するからである。URLをパーズする必要はない。
var current_nav = $("body").data("current-nav");
$("nav ul li."+current_nav).addClass("current");
htmlタグやbodyタグごとインクルードしてて、且つサーバサイドで解決できない場合?それは設計に無理がある気がするが、それでもJSを使えばなんとかなるので頑張ろう。