Bootstrap4を使用してナビメニューを作っている時にはまった内容です。
最終的にはJQueryを使用して無理やり解決したので、その内容を共有したいと思います。
うんこーどですが、一例としてどうぞ。
やりたいこと
・縦積みナビメニューで一部を折り畳み。
・選択中のピルは色を変える。
コード
以下が最初に作ったコードです。
折り畳まれるメニューと上段のメニューの表示非表示が連動しません。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"></meta>
<title>nav</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"></link>
</head>
<body>
<div class="container-fluid">
<div class="row">
<nav>
<div class="nav nav-pills flex-column" aria-orientation="vertical">
<a class="nav-link active"aria-selected="true" data-toggle="pill">メニュー1</a>
<a class="nav-link" aria-selected="false" data-toggle="pill">メニュー2</a>
<span class="nav-link dropdown-toggle"
data-toggle="collapse"
data-target="#fold-menu"
aria-controls="fold-menu"
aria-expanded="false">メニュー3</span>
<div class="collapse" id="fold-menu">
<div class="nav nav-pills flex-column">
<a class="nav-link ml-4" aria-selected="false" data-toggle="pill">サブメニュー1</a>
<a class="nav-link ml-4" aria-selected="false" data-toggle="pill">サブメニュー2</a>
</div>
</div>
<a class="nav-link" aria-selected="false" data-toggle="pill">メニュー4</a>
</div>
</nav>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"
integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
</body>
</html>
JQueryを使って直したコードが以下です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"></meta>
<title>nav</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"></link>
</head>
<body>
<div class="container-fluid">
<div class="row">
<nav>
<div class="nav nav-pills flex-column" aria-orientation="vertical" id="pill-list">
<a class="nav-link active"aria-selected="true">メニュー1</a>
<a class="nav-link" aria-selected="false">メニュー2</a>
<span class="nav-link dropdown-toggle"
data-toggle="collapse"
data-target="#fold-menu"
aria-controls="fold-menu"
aria-expanded="false">メニュー3</span>
<div class="collapse" id="fold-menu">
<div class="nav nav-pills flex-column">
<a class="nav-link ml-4" aria-selected="false">サブメニュー1</a>
<a class="nav-link ml-4" aria-selected="false">サブメニュー2</a>
</div>
</div>
<a class="nav-link" aria-selected="false">メニュー4</a>
</div>
</nav>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"
integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<script>
$('#pill-list a').on('click',function (e) {
e.preventDefault()
$('#pill-list a').removeClass('active show');
$(this).tab('show')
})
</script>
</body>
</html>
改修前後の違い
・各メニュー(<a>タグ)からdata-toggle="pill"を外す。
・最上位の div.nav にidを追加
・選択切り替えのスクリプト追加
ちなみに
この記事を書きつつドキュメントを見ていたら、
こんな文章を発見しました。
動的タブ付きインタフェースには、ユーザビリティとアクセシビリティの両方の問題が発生するためドロップダウンのメニューを入れてはいけない。ユーザビリティの観点からは、現在表示されているタブの切替え要素が(閉じられたドロップダウンのメニューの中にあるので)すぐには見えないという事実が混乱の原因となる。
頑張って折り畳めるようにしましたが、サブメニューを選択した状態で折り畳めるため、
ドロップダウンと同様に見えなくなって混乱の原因になるっていう・・・。
残念!
おまけ
おかしな挙動の素
折り畳まれるメニューを囲っている以下のタグをはずすと当たり前ですがちゃんと動いてくれます。
・<div class="collapse" id="fold-menu">
・<div class="nav nav-pills flex-column">
<div class="collapse" id="fold-menu">
だけをはずすとこんな感じ。
<div class="nav nav-pills flex-column">
だけをはずすとこんな感じ。
ナビメニューの内側にナビメニューを入れると、
別グループだと認識されるみたい?
んーよくわからない・・。
パネル(タブ選択で表示が切り替わるところ)を追加しても同じ。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"></meta>
<title>nav</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"></link>
</head>
<body>
<div class="container-fluid">
<div class="row">
<nav>
<div class="nav nav-pills flex-column" aria-orientation="vertical">
<a class="nav-link active"aria-selected="true" data-toggle="pill" id="menu1" href="#menu1-content" aria-controls="menu1-content">メニュー1</a>
<a class="nav-link" aria-selected="false" data-toggle="pill" id="menu2" href="#menu2-content" aria-controls="menu2-content">メニュー2</a>
<span class="nav-link dropdown-toggle" data-toggle="collapse" data-target="#fold-menu" aria-controls="fold-menu" aria-expanded="false">メニュー3</span>
<div class="collapse" id="fold-menu">
<div class="nav nav-pills flex-column">
<a class="nav-link ml-4" aria-selected="false" data-toggle="pill" id="sub-menu1" href="#sub-menu1-content" aria-controls="sub-menu1-content">サブメニュー1</a>
<a class="nav-link ml-4" aria-selected="false" data-toggle="pill" id="sub-menu2" href="#sub-menu2-content" aria-controls="sub-menu2-content">サブメニュー2</a>
</div>
</div>
<a class="nav-link" aria-selected="false" data-toggle="pill" id="menu4" href="#menu4-content" aria-controls="menu4-content">メニュー4</a>
</div>
</nav>
<div class="p-5">
<div class="tab-content">
<div class="tab-pane show active" id="menu1-content" aria-labelledby="menu1">
<p>メニュー1</p>
</div>
<div class="tab-pane" id="menu2-content" aria-labelledby="menu2">
<p>メニュー2</p>
</div>
<div class="tab-pane" id="sub-menu1-content" aria-labelledby="sub-menu1">
<p>サブメニュー1</p>
</div>
<div class="tab-pane" id="sub-menu2-content" aria-labelledby="sub-menu2">
<p>サブメニュー2</p>
</div>
<div class="tab-pane" id="menu4-content" aria-labelledby="menu4">
<p>メニュー4</p>
</div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"></meta>
<title>nav</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"></link>
</head>
<body>
<div class="container-fluid">
<div class="row">
<nav>
<div class="nav nav-pills flex-column" aria-orientation="vertical" id="pill-list">
<a class="nav-link active"aria-selected="true" id="menu1" href="#menu1-content" aria-controls="menu1-content">メニュー1</a>
<a class="nav-link" aria-selected="false" id="menu2" href="#menu2-content" aria-controls="menu2-content">メニュー2</a>
<span class="nav-link dropdown-toggle" data-toggle="collapse" data-target="#fold-menu" aria-controls="fold-menu" aria-expanded="false">メニュー3</span>
<div class="collapse" id="fold-menu">
<div class="nav nav-pills flex-column">
<a class="nav-link ml-4" aria-selected="false" id="sub-menu1" href="#sub-menu1-content" aria-controls="sub-menu1-content">サブメニュー1</a>
<a class="nav-link ml-4" aria-selected="false" id="sub-menu2" href="#sub-menu2-content" aria-controls="sub-menu2-content">サブメニュー2</a>
</div>
</div>
<a class="nav-link" aria-selected="false" id="menu4" href="#menu4-content" aria-controls="menu4-content">メニュー4</a>
</div>
</nav>
<div class="p-5">
<div class="tab-content">
<div class="tab-pane show active" id="menu1-content" aria-labelledby="menu1">
<p>メニュー1</p>
</div>
<div class="tab-pane" id="menu2-content" aria-labelledby="menu2">
<p>メニュー2</p>
</div>
<div class="tab-pane" id="sub-menu1-content" aria-labelledby="sub-menu1">
<p>サブメニュー1</p>
</div>
<div class="tab-pane" id="sub-menu2-content" aria-labelledby="sub-menu2">
<p>サブメニュー2</p>
</div>
<div class="tab-pane" id="menu4-content" aria-labelledby="menu4">
<p>メニュー4</p>
</div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script>
$('#pill-list a').on('click',function (e) {
e.preventDefault()
$('#pill-list a').removeClass('active show');
$(this).tab('show')
})
</script>
</body>
</html>
おわり
フロント側はなかなか難しいですねぇ。
実際に使う人が見る触れる部分なので、
さくっといい感じに作れるように早くなりたいものです。
あと、センスが欲しい。
とりあえず、今回は以上です。
参考
Bootstrap4移行ガイド - ナビゲーション(Navs)
http://cccabinet.jpn.org/bootstrap4/components/navs#flex-column-nav-pills