WordPressでテーマ開発をするとき、ほぼ必ず実装するのがヘッダーやフッターに配置するメニュー。
通常は管理画面の「外観」→「メニュー」で作成して、テーマ側では出力設定をするだけでOKですが、案件によっては静的に組むこともあります。
また、メニューには投稿の一覧ページへのリンクを設置して、その投稿詳細ページが開いている時は一覧ページリンクにカレント設定をしたい。固定ページの場合は親と子で同じようなカレント設定がしたい場合も。
このような場合は少しテーマ側で工夫してあげる必要があるので備忘録がわりにご紹介します。
※サクッと本題を見たい人は【本題】まで飛ばしてください。
メニューを静的に組む場合は下記の記事をご参考にしてください。
通常のメニューの作り方
まずは通常の方法でメニューを作る場合。
WordPressの管理画面から「外観」→「メニュー」を選択して、メニューの内容を作成します。
表示したい位置を設定する場合は下の部分にチェックを入れてください。
これだけでメニューは作れているので、テーマ側で出力設定がされていれば完成です。
現在表示しているページには、自動で「.current-menu-item」というクラスがli要素に付与されるので、cssでデザインを変更すればカレント設定完了です。
※テーマ側での出力設定
オリジナルテーマを作成している、もしくはテーマの改修をする場合では作成したメニューを出力する記述をする必要があります。
通常はheader.phpもしくはfooter.phpに下記のように記述します。
if(has_nav_menu('メニュー名'){
wp_nav_menu(['theme_location' => 'メニュー名']);
}
header.php1行目 if(has_nav_menu(‘メニュー名’) では、メニューが存在しているかどうかを確認します。この記述がないと、表示位置にチェックをしていなくてもメニューが表示されるので、レイアウト崩れ等の原因になります。
2行目 wp_nav_menu([‘theme_location’ => ‘メニュー名’]); が実際にメニューを表示する記述です。
wp_nav_menu()は、引数をしてすることで表示するメニューの内容や表示方法(メニューを囲むタグの設定など)を指定することができます。
↓引数とデフォルト設定
wp_nav_menu( array(
'menu' => '',
'menu_class' => 'menu',
'menu_id' => '',
'container' => 'div',
'container_class' => '',
'container_id' => '',
'container_aria_label' => '',
'fallback_cb' => 'wp_page_menu',
'before' => '',
'after' => '',
'link_before' => '',
'link_after' => '',
'echo' => true,
'depth' => 0,
'walker' => '',
'theme_location' => '',
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
'item_spacing' => 'preserve'
) );
header.php引数は配列で指定する必要があるので、array()か[]を使って指定します。
最低限menuとtheme_locationだけは覚えておくと便利です。(どちらも表示するメニューを指定するもので、使いわけは後述します。)
※表示位置を増やす方法
管理画面からメニューを追加するときに、表示したい箇所にチェックを入れましたが、このチェック欄はテーマファイルをカスタマイズすることで自由に増やすことができます。
function my_add_menu() {
register_nav_menus(array(
'header_menu' => 'ヘッダーメニュー',
'footer_menu1' => 'フッターメニュー1',
'footer_menu2' => 'フッターメニュー2'
));
}
add_action('after_setup_theme','my_add_menu');
functions.php3~5行目は自由に設定でき、配列のキーとなる(左側にある)header_menuやfooter_menu1というのが、wp_nav_menu()のtheme_locationで指定する場合に使います。
配列の値(右側)のヘッダーメニューやフッターメニュー1は、wp_nav_menu()のmenuで使います。(管理画面のチェックボックスとしても表示されます)
↓menuを使ってヘッダーメニューを指定する方法
if(has_nav_menu('header_menu'){
wp_nav_menu(['menu' => 'ヘッダーメニュー']);
}
header.php↓theme_locationを使ってヘッダーメニューを表示する方法
if(has_nav_menu('header_menu'){
wp_nav_menu(['theme_location' => 'header_menu']);
}
hedaer.phpどちらでも同じメニューを表示できますが「has_nav_menu()」の引数にはmenuの値ではなくlocationの値を使う必要があるのが、個人的にはmenuによる指定はほぼ使わず、theme_locationを使った後者の記述だけを使っています。
【本題】親メニューにカレント設定をするにはどうしたらいいのか
基本的な使い方がわかったところで、今回の本題。
WordPressの通常のメニューだけだと、投稿の詳細をページを開いているときに、その一覧ページのリンクを表示するメニューにカレント用のクラスがつきません。
解決するにはJavaScriptを使ってフロント側で対応するか、PHPを使ってサーバー側で対応するかの2つのパターンが考えられます。
JavaScriptで対応する方法
JavaScriptで対応する方法としては、今開いているページのURLを取得し、該当するページであれば対象のURLに「.current-menu-item」というクラスをつけるような実装をします。
// 今表示しているURLを取得
let currentUrl = window.location.href;
// カスタム投稿タイプのURLの共通部分を設定
const targetUrl = "https://xxx.com/blog";
// ターゲットになるメニューの指定
const targetMenu = document.querySelectorAll('.js-add-current');
// 条件に一致したときにメニューに.current-menu-itemを追加
if (currentUrl.includes(targetUrl)) {
targetMenu.forEach(menuItem => {
menuItem.classList.add('current-menu-item');
});
}
headerMenu.js5行目の targetUrlには、対象の投稿の共通部分になるURLを追加してください。(パーマリンクの設定によって異なります)
例えば、「blog」というカスタム投稿を追加していて、詳細ページのURLが「https://xxx.com/blog/(投稿ID)」となっている場合、「https://xxx.com/blog」が共通部分として条件分岐に使うことができます。
8行目ではカレントをつけるメニューを指定していますが、簡単な方法としてはWordpressの管理画面で対象となるメニューに「.js-add-current」など判別用のクラスを付与してしまう方法です。
管理画面の「外観」→「メニュー」を開いてから画面右上の「表示オプション」を押して「cssクラス」にチェックを入れることで各メニュー(li要素)にクラスをつけることができます。
上記の設定をしたら、クラスをつけたいメニューを選んで「.js-add-current」というクラスを設定します。(カンマは不要で、複数クラスを指定する場合は半角スペースで区切ってください)
この方法で実装する場合、blogというカスタム投稿に対して、メニューの種類がカスタムリンクでも固定ページでもアーカイブリンクでも汎用的に使うことができます。
一方でjsで実装するため、実装状況によっては表示に一瞬のタイムラグが生じる可能性があります。
また、複数のカスタム投稿タイプを使用する場合、.js-add-currentのクラス名を別に用意してjsもそれに対応して複数作ってあげれば対応できると思います。
PHPで対応する場合
PHPで対応する場合はWordpressのフィルターフックを使って制御することができます。
JavaScriptの例と同じように「blog」というカスタム投稿に対して対応するには、下記のようなコードをfunctions.phpに追加してください。(※必ずバックアップを取り、ローカル環境・テスト環境で動作チェックをてください)
function add_nav_current($classes, $item){
// メニューでアーカイブリンクが使える場合
if($item -> type == 'post_type_archive'){
$post_type = $item -> object;
if(is_singular($post_type)){
$classes[] = 'current-menu-item';
}
}
// カスタムリンク等で追加する場合
if($item -> title == 'ブログ'){ // ブログはメニューのタイトル名
if(is_singular('blog')){ // blogはカスタム投稿のスラッグ
$classes[] = 'current-menu-item';
}
}
return $classes;
}
add_filter( 'nav_menu_css_class', 'add_nav_current', 10, 2 );
functinos.php3~9行目、もしくは11~16行目のどちらかを使って実装してください。
どちらを選ぶかは管理画面でメニューを追加するときの方法によって異なります。
アーカイブリンクとして追加している場合は前者、カスタムリンクや固定ページとして追加している場合は後者を使ってください。
まとめ
今回はWordpressの標準メニューを使った場合のカレント設定についてご紹介しました。冒頭でも少し触れましたが、メニュー部分については静的に組むこともあるので、そのうち静的に組んだメニューのカレント設定についても解説したいと思います。
UI/UXの向上のためにもカレント設定は必要な知識・技術です。
初学者の方や案件を始めたばかりの方であれば、クライアントから特に指示がなくてもカレント設定のご提案ができると、コーダーとしての信頼度も勝ち取りやすくなるので試してみてくださいね。