スマホ用メニューをウィジェットを活用し、プラグインなしで実装してみました。
ところがスマホの場合、第1階層メニュー(以下、親メニューとします)のマウスオーバーで第2階層メニュー(以下、サブメニューとします。WordPressメニュー項目では「副項目」となっています。)を開閉することができないため、試行錯誤しました。
プラグインに頼ろうと諦めかけていたのですが、アイデアを駆使した結果、タップで無事サブメニューを開閉することができましたので備忘録として残しておきます。
アイデアの要点を先に知りたい方は、目次から最後の項目に進んでください。
状況
- jQueryの「hover()」メソッドを使って、PC上では親メニューのマウスオーバーでサブメニューを開閉できることは確認済み。
- スマホの場合、親メニューをタップすると、サブメニューは開閉されずに親ページに遷移してしまう。
- WordPressのバージョンは5.7.2
試したこと諸々
- jQuery「prepend()」メソッドを使って下向き矢印アイコンを追加し、後から追加した要素にイベントハンドラを登録することになるため、「$(‘.parent’).on(‘click’, ‘.child’, function() { ~」という、第2引数にイベント発生元を指定するセレクタを記述する方法で試したもの失敗。
- jQuery「preventDefault()」メソッドでページ遷移の制御を試みるも失敗。
- モバイルでもマウスオーバーのように振舞ってくれる、
ontouchstart
イベント、対象要素にontouchstart=""
という属性を追加する等も失敗、たとえ成功したとしても少々不安感あり。
解決方法
手順は少々多いですが、ひとつひとつは複雑でもなく、難易度は高くないです。
スマホメニューのプラグインを導入するにしても、それなりの設定作業が必要ですから。
使用するもの
- HTMLファイル(各種読込)
- functions.phpファイル(サイドバーエリアを追加)
- header.phpファイル(ウィジェットを表示)
- WordPress管理画面のウィジェット、メニュー項目
- JavaScriptファイル
- CSSファイル(SCSSを使用)
事前準備
- jQuery及びご利用のJSファイル、CSSファイルをHTMLファイルで読み込みます(詳細説明割愛)。
- Font Awesomeに登録し、同じくHTMLファイルで読み込みます(詳細説明割愛、こちらの記事にFont Awesome読み込みについて記載した箇所があります)。
実装手順
functions.phpファイルでサイドバーエリア追加
<?php
//ウィジェットエリア
function my_theme_widgets_init() {
register_sidebar(array(
'name' => 'sp-menu',
'id' => 'sp-menu-widget-area',
'description' => 'SPでメニューに表示されるウィジェットエリアです。',
));
}
add_action( 'widgets_init', 'my_theme_widgets_init' );
?>
WordPress 管理画面メニュー新規作成
「外観」>「メニュー」の「メニューを編集」タブの中の上部に表示される「新しいメニューを作成しましょう。」をクリックし、新規メニューを作成します。
青枠の箇所がサブメニューを持ったアイコンのみのダミーの親ページとなります。
Font Awesomeの下向きの矢印を設定しています。
![management-screen](https://weblog.b-moon.net/wp-content/uploads/2021/06/sample-menu-min-1006x1024.png)
WordPress ナビゲーションメニューをウィジェットに追加
「外観」>「ウィジェット」の左側画面にある、「ナビゲーションメニュー」から、functions.phpで新規作成したサイドバーエリアを選択し、「ウィジェットを追加」を押下します。
![navigation-menu](https://weblog.b-moon.net/wp-content/uploads/2021/06/navi-menu-min.png)
WordPress サイドバーに作成したウィジェットエリアに追加
同じく、「外観」>「ウィジェット」の右側画面にある、新規作成したサイドバーエリアで、メニューを選択し、「完了」を押下します。
プルダウンメニューが表示されない場合は、一度管理画面を再読み込みしてください。
![widget](https://weblog.b-moon.net/wp-content/uploads/2021/06/widget-min.png)
header.phpファイルにてウィジェットを表示
<div class="sp-menu">
<?php if ( is_active_sidebar('sp-menu-widget-area') ) : ?>
<?php dynamic_sidebar('sp-menu-widget-area'); ?>
<?php endif; ?>
</div>
jQueryでリンクの解除とイベント登録
ダミーの親メニューアイコンについた親ページへのリンクを解除して、クリックイベントを登録します。
$(‘.shop-sub-menu-btn’).unwrap(); この部分で親要素aタグを削除し、親ページへの遷移を制御しています。
※後日追記 後から気づいたのですが、画面をリサイズするとウィジェットのメニューが表示されてしまうため、それらの各メニューアイテムをhide()メソッドで非表示にし、クリックイベント後にtoggle()メソッドで表示することにしました。また、サイトマップ等でもウィジェットエリアを設定している場合は、そちらも非表示になってしまう恐れもありますので、適宜ご調整ください。
// メニュースライドダウン
$(window).on('load resize', function(){
//メニューアイコンを押した時にメニューが表示される処理を記述(省略)
//(追記)画面をリサイズ時に表示されるウィジェットアイテムをhide()メソッドで非表示
//スマホ、タブレット(768pxと想定)はタップでサブメニューを開閉
var winW = $(window).width();
if (winW <= 768) {
// pcでメニューアイコン不使用の場合は、条件式不要なので、以下 } else { までのみでよいかと
$('.shop-sub-menu-btn').unwrap()
$('.shop-sub-menu-btn').click(function() {
$(this).next('.sub-menu').stop(true,true).slideToggle(100);
$(this).toggleClass('active');
//(追記)hide()メソッドで非表示した要素にtoggle()メソッドを追加
});
} else {
//pcはマウスオーバーでサブメニューを開閉
$('.menu-item-has-children').unbind().hover(function(){
$(this).children('.sub-menu').stop(true,true).slideToggle(100);
});
};
});
CSSで位置等調整
当然ながらダミーの親メニューアイコンは、前の本来の親メニューの直下に表示されるため、位置を調整する必要があります。
全体のフォントサイズはSCSSでカスタマイズしているので、適宜調整してください。
.menu-global-menu-container {
margin: 0 auto;
padding: 5% 0 5%;
width: 80%;
ul {
display: block;
/* 親メニュー*/
li {
padding: 0.4rem 0;
a {
font-size: 2rem;
color: $base-color;
}
/* サブメニュー*/
.sub-menu {
display: none;
padding-left: 1rem;
li {
display: inline-block;
margin: 0 1rem;
a {
font-size: 1.6rem;
}
}
}
}
/* ダミーの親メニューのアイコンの位置調整 */
.menu-item-has-children {
position: relative;
span {
position: absolute;
top: -3.5rem;
right: 0;
display: inline-block;
width: 3.2rem;
height: 3.2rem;
cursor: pointer;
text-align: center;
transition: 0.4s ease-in-out;
.fa-angle-down {
font-size: 3rem;
color: $base-color;
font-weight: 700;
}
}
/* クリック時に付与したクラスにて矢印アイコンを180度回転 */
.active {
transform: rotate(180deg);
}
}
}
}
アイデアの要点
詳細説明は割愛させていただいている部分もありますが、要するにWordPress管理画面のウィジェットに追加するメニューに、親メニューとは別に、サブメニューを持つアイコンだけのダミーの親メニューを追加し、その要素自身のリンクを外した上でクリックイベントを追加するということです。