LoginSignup
2
0

More than 5 years have passed since last update.

Bootstrap4でナビメニューの一部を折り畳みにすると選択(active)の挙動がおかしくなった。

Posted at

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>

nav-menue1-devtool.gif

JQueryを使って直したコードが以下です。

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>

nav-menue-fix-devtool.gif

改修前後の違い

・各メニュー(<a>タグ)からdata-toggle="pill"を外す。
・最上位の div.nav にidを追加
・選択切り替えのスクリプト追加

ちなみに

この記事を書きつつドキュメントを見ていたら、
こんな文章を発見しました。

動的タブ付きインタフェースには、ユーザビリティとアクセシビリティの両方の問題が発生するためドロップダウンのメニューを入れてはいけない。ユーザビリティの観点からは、現在表示されているタブの切替え要素が(閉じられたドロップダウンのメニューの中にあるので)すぐには見えないという事実が混乱の原因となる。

頑張って折り畳めるようにしましたが、サブメニューを選択した状態で折り畳めるため、
ドロップダウンと同様に見えなくなって混乱の原因になるっていう・・・。

残念!

おまけ

おかしな挙動の素

折り畳まれるメニューを囲っている以下のタグをはずすと当たり前ですがちゃんと動いてくれます。
<div class="collapse" id="fold-menu">
<div class="nav nav-pills flex-column">

nav-menue-4-devtool.gif

<div class="collapse" id="fold-menu">だけをはずすとこんな感じ。

nav-menue2-devtool.gif

<div class="nav nav-pills flex-column">だけをはずすとこんな感じ。

nav-menue3-devtool.gif

ナビメニューの内側にナビメニューを入れると、
別グループだと認識されるみたい?
んーよくわからない・・。

パネル(タブ選択で表示が切り替わるところ)を追加しても同じ。

挙動がおかしい奴
<!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>

nav-menue1-pane.gif.gif

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" 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>

nav-menue2-pane.gif.gif

おわり

フロント側はなかなか難しいですねぇ。

実際に使う人が見る触れる部分なので、
さくっといい感じに作れるように早くなりたいものです。
あと、センスが欲しい。

とりあえず、今回は以上です。

参考

Bootstrap4移行ガイド - ナビゲーション(Navs)
http://cccabinet.jpn.org/bootstrap4/components/navs#flex-column-nav-pills

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0