WordPressのメニューをカスタマイズするのに便利なフィルターフック「nav_menu_link_attributes」の使い方と応用例を紹介します。
nav_menu_link_attributesの使い方
nav_menu_link_attributesとは、メニュー項目のリンク(<a>要素)のHTML属性を変更できるフィルターフックです。
下記のような感じで、リンクに付与するHTML属性を配列で返します。
<?php
function edit_menu_link( $atts, $menu_item, $args, $depth ) {
$atts['属性名'] = '属性値';
return $atts;
}
add_filter( 'nav_menu_link_attributes', 'edit_menu_link', 10, 4 );
?>
最大で4つのパラメーターを受け取ります。それを使うと結構複雑な条件分岐も可能なので、なかなか便利な使い方ができるというわけです。
パラメーター①:属性
上記コードで言うと、edit_menu_linkの引数「$atts」は、リンクに付与されている属性を配列で受け取ります。
例えばhref属性は「$atts[‘href’]」で取得できます。
通常は以下のような属性が入っていることでしょう。
- title属性
- target属性
- rel属性
- href属性
- area-current属性
パラメーター②:メニュー項目の情報
それぞれのメニュー項目が持っている情報をオブジェクトで受け取ります。
例えば「$menu_item->description」でメニュー項目の「説明」に入力した値が取得できます。
どんな値が入っているかは‥‥‥一度var_dumpで見てみるのが早いでしょう。(手抜き)
パラメーター③:wp_nav_menu()の引数
メニューを出力する関数「wp_nav_menu」に与えた引数をオブジェクトで受け取れます。
例えば「$args->theme_location」でメニュー位置を取得できます。
パラメーター④:階層の深さ
それぞれのメニュー項目が置いてある階層の深さをゼロから始まる数値で受け取ります。
返り値:属性
リンク要素に付与される全属性を配列で返します。
パラメーター①で受け取った配列に処理を加えたものを戻す形になるでしょう。
nav_menu_link_attributesの応用例
nav_menu_link_attributesを使ったメニューのカスタマイズ例を幾つか紹介します。
そのまま使うというより「こういう使い方ができるんだな」という感覚をつかめるように、かなり単純化したサンプルになっています。
感覚がつかめれば、さらにニーズに合わせて応用できるはず。
a要素にclassなどの属性を付ける
通常だと下記のようにli要素にクラスが付いているので、CSSでa要素を指定したい場合は「li.menu-item > a」という感じになります。
<ul class="menu">
<li class="menu-item"><a href="xxxxx">メニュー</a></li>
</ul>
でも、例えばメニュー以外のパーツとスタイルを共通化したい時とか、a要素自体にクラスが付いているほうが都合が良い時って結構あります。
そこで、下記のような処理を加えます。
function edit_menu_link( $atts ) {
$atts['class'] = 'button';
return $atts;
}
add_filter( 'nav_menu_link_attributes', 'edit_menu_link', 10 );
すると、上記のHTMLが以下のように変わります。
<ul class="menu">
<li class="menu-item"><a href="xxxxx" class="button">メニュー</a></li>
</ul>
この例ではclassですが、他にも色々な属性を付けることができます。
id属性、data属性、style属性など、なんでも好きに付けられるので夢が広がりますね!
階層によって異なるclassを付ける
パラメーター④のdepthを使えば、「この階層の時はこの属性値を付ける」という処理ができます。
下の例では、一番上の階層の時だけ「menu-button」というクラス、下の階層にある項目には深さに関係なく「menu-button_sub」というクラスが追加されます。
<?php
function edit_menu_link( $atts, $item, $args, $depth ) {
if ( $depth == 0 ) {
$atts['class'] = 'menu-button';
}else{
$atts['class'] = 'menu-button_sub';
}
return $atts;
}
add_filter( 'nav_menu_link_attributes', 'edit_menu_link', 10, 4 );
?>
ul要素、li要素が入れ子になるとCSSがわけわからなくなりがちなので、こうやってa要素をクラス分けしてやると分かりやすくなります。
特定のメニューを指定して処理する
今までのコードだと、全てのメニューに対して処理が行われることになります。
例えば「グローバルナビの時だけ、メニューのa要素にclassを付けたい」というときはどうするかと言うと、こうします。
function edit_menu_link( $atts, $item, $args ) {
if( $args->theme_location == 'global_nav' ) {
$atts['class'] = 'menu-button';
}
return $atts;
}
add_filter( 'nav_menu_link_attributes', 'edit_menu_link', 10, 3 );
要するにwp_nav_menuの引数で「’theme_location’ => ‘global_nav’」を指定しているかどうかを判定しています。
ページ内リンクにパスを付ける
hrefやtitleといった、a要素に既に付いている属性を上書きすることだってできます。
一例として、グロナビのメニュー項目にページ内リンクを設定して、どのページからでもフロントページの該当セクションに飛べるようにしたい場合。
メニュー項目でカスタムリンクを選択して、urlに「#xxxxx」とページ内リンクを指定します。これだとフロントページでは動作するけど、他のページからだと迷子になってしまいます。
なので普通だったら「https://xxxxxx.com/#xxxxx」とホームのパスを入れてあげればいいのですが、『引っ越した時に書き換えなきゃいけないのがなんかイヤ!』と意地を張りたいこともあるでしょう。
そんな時はこちら。
function edit_menu_link( $atts ) {
if( !is_front_page() ){
$href = $atts['href'];
if( substr($href, 0, 1) === '#' ) {
$atts['href'] = home_url('/'). $href;
}
}
return $atts;
}
add_filter( 'nav_menu_link_attributes', 'edit_menu_link', 10 );
フロントページの時は何もせずにそのまま$attsを返します。
フロントページ以外の時はhref属性の値を取得して、先頭の文字が「#」で始まる場合はホームページのパスを挿入します。
日本語メニューに英語表記を添える
もちろん、今回の手法では「<a href=””>ワードプレス<span class=”en”>Wordpress</span></a>」みたいにHTML構造を変えることはできません。
いじれるのはa要素自体の属性のみ。
でも、飾りで英字を添えるくらいのことなら、HTML属性とCSS疑似要素を使って実現できます。
これは別記事に書いたので、詳しくはこちらをご覧ください。
何かと便利なnav_menu_link_attributes
いかがでしたか?
リンク要素のHTML属性をいじる、という地味なフィルターフックですが、意外といろんな場面で応用できそうです。
コメント