質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.06%

Javascript/css ドロワーメニュー外をクリックした時に、メニューを閉じれるようにしたい

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 198

Nogeira

score 1

前提・実現したいこと

WEBサイトのドロワーメニューをCSSとJavascriptで作成しております。
メニューオープン時、メニュー外クリックでも閉じれる機能をJavascriptで実装したいのですが、上手くいきません。

ハンバーガーボタンクリックによる開閉は実装済です。

発生している問題・エラーメッセージ

document.addEventListener('click'....で新たにfunctionを作ってみたが、
ボタンを押してもメニューがスライドして出てこない等上手くいかない。

該当のソースコード

<section class="anime-renshu3">
    <a class="drawer-menu">
      <div></div>
      <div></div>
      <div></div>
    </a>
    <nav class="nav-menu">
      <ul>
        <li><a href="#">menu1</a></li>
        <li><a href="#">menu2</a></li>
        <li><a href="#">menu3</a></li>
      </ul>
    </nav>
    <div class="anime-tate">
      <h2>広大な空を旅しよう</h2>
    </div>
    <div class="overlay"></div>
  </section>
  /* anime-renshu3 */
  .anime-renshu3 {
    background: url(http://sozai.yutorilife.com/s19201200/photo/umi03.jpg);
    background-position: top right;
    background-size: cover;
    height: 100vh;
    position: relative;
    overflow: hidden;
    z-index: 3;
  }

  .anime-tate {
    display: inline-block;
    overflow: hidden;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  .anime-tate h2 {
    font-weight: 900;
    font-size: 3vw;
    color: #fff;
    background: rgba(0,0,0,.5);
    padding: 30px;
    writing-mode: vertical-rl;
    text-orientation: mixed;
    visibility: hidden;
  }

  @keyframes tate-play {
    from {
      transform: translateY(-100%);
    }

    to {
      transform: translateY(0);
    }
  }

  @keyframes tate-mask {
    from {
      opacity: : translateY(0);
    }

    to {
      transform: translateY(100%);
    }
  }

  .tate-start {
    animation-name: tate-play;
    animation-duration: .3s;
    animation-fill-mode: forwards;
    animation-timing-function: ease;
    position: relative;
    visibility: visible !important;
  }

  .tate-start::before {
    animation-name: tate-mask;
    animation-duration: .5s;
    animation-delay: .5s;
    animation-fill-mode: forwards;
    animation-timing-function: ease-in;
    position: absolute;
    content: '';
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
    background: #fff;
  }

  /* .humburger-menu } */
  .drawer-menu {
    display: block;
    width: 80px;
    height: 80px;
    background: #193374;
    position: fixed;
    top: 0;
    right: 0;
    transition: all .8s;
    z-index: 8;
  }

  .drawer-menu div {
    height: 1px;
    width: 50%;
    background: #fff;
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    transition: .5s;
  }

  .drawer-menu div:nth-of-type(1) {
    transform: translate(-50%, -10px);
  }

  .drawer-menu div:nth-of-type(3) {
    transform: translate(-50%, 10px);
  }
  /* menu-open class add event*/
  .drawer-menu.menu-open div:nth-of-type(1) {
    transform: rotate(45deg) translate(-50%, 0px);
    transform-origin: 0% 50%;
  }

  .drawer-menu.menu-open div:nth-of-type(2) {
    opacity: 0;
  }

  .drawer-menu.menu-open div:nth-of-type(3) {
    transform: rotate(-45deg) translate(-50%, 0px);
    transform-origin: 0% 50%;
  }

  .nav-menu {
    display: block;
    width: 400px;
    height: 100%;
    position: fixed;
    top: 0;
    right: 0;
    transform: translate(100%, 0);
    transition: .3s ease-in-out;
    background: rgba(25,51,116,.7);
    z-index: 7;
  }

  .nav-menu ul li {
    list-style: none;
    padding: 30px;
  }
  .nav-menu ul li a {
    color: #fff;
    text-decoration: none;
  }
  .nav-menu.active {
    transform: translate(0, 0);
  }

  .overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: none;
    position: fixed;
    z-index:6;
  }

  .overlay.active {
    background: rgba(0,0,0,.6);
  }
    /* fullscreen subtitle load */
    window.addEventListener('load', function() {
      const element = document.querySelectorAll('.anime-renshu3');
      element.forEach((items) => {
        items.querySelector('.anime-tate h2').classList.add('tate-start');
      });
    });


    /* humburger menu click */
    document.querySelector('.drawer-menu').addEventListener('click', function() {
      this.classList.toggle('menu-open');

      const element = document.querySelector('.drawer-menu');
      const elem = document.querySelector('.nav-menu');
      const overlay = document.querySelector('.overlay')

      if(elem.classList.contains('active')) {
          elem.classList.remove('active');
          element.style.background = '#193374';
          overlay.classList.remove('active');
      } else {
        elem.classList.add('active');
        /*ボタン背景透過処理*/
        element.style.background = 'rgba(25,51,116,0)';
        /*active時暗くなる*/
        overlay.classList.add('active');
      }
    });

試したこと

document.addEventListener('click' function()...
で.nav-menuをremoveする処理を試しましたが、
.drawer-menuをクリックしてもメニューがスライドしてきません。

補足情報(FW/ツールのバージョンなど)

windows10 64bit
Chrome バージョン: 80.0.3987.122

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

bodyをクリックした時に、
.anime-renshu3要素内のクリックじゃないか判別して、
.drawer-menuの要素を(JavaScriptで)クリックするコードを書けばよいです。

【event.curretTargetとevent.targetの違い - gsol-dev's blog】
http://gsol.hatenablog.com/entry/2013/12/04/event.curretTarget%E3%81%A8event.target%E3%81%AE%E9%81%95%E3%81%84

【Element.closest() - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/Element/closest

【Event() - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/Event/Event


jQuery のほうが簡単に書ける。
(※ 下記コードはメニューが開いているかどうかを確認していないため、閉じている時にほかのものをクリックしたらメニューが開きます)

$( function() {
  $( 'body' ).on( 'click', function( e ) {
    var b = $( e.target ).closest( '#menu' ).length;
    if ( b == 0 ) { // #menu 以外なら
        $( '#menu' ).trigger( 'click' );
    }
  } );
  $( '#menu' ).on( 'click', function( e ) {
    $( '#box' ).toggle();
  } );
} ); // 例

動くサンプル:https://jsfiddle.net/v192e0bu/


【.on() | jQuery API Documentation】
https://api.jquery.com/on/

【.trigger() | jQuery API Documentation】
https://api.jquery.com/trigger/

【.closest() | jQuery API Documentation】
https://api.jquery.com/closest/
【EventTarget.dispatchEvent() - Web API | MDN】
https://developer.mozilla.org/ja/docs/Web/API/EventTarget/dispatchEvent

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/02 01:41

    申し訳ないです、今回はJavascriptのみでの実装を考えてます。

    教えて頂いた構文をちゃんと理解はできてないんですが、一応参考にして

    document.querySelector('body').addEventListener('click', function(e) {
    const element = document.querySelector('.drawer-menu');
    const elem = document.querySelector('.nav-menu');
    const overlay = document.querySelector('.overlay');

    if(!$(e.target).closest('.drawer-menu').length) {
    elem.classList.remove('active');
    element.style.background = '#193374';
    overlay.classList.remove('active');
    element.classList.remove('menu-open');
    }
    });

    と書いてそれっぽい動きにはなりましたが、
    これだとどこを押しても閉じてしまいます。

    キャンセル

  • 2020/03/02 01:43

    jQuery は Javascriptで実装されていますよ。

    キャンセル

  • 2020/03/02 01:46

    それは存じております。

    キャンセル

  • 2020/03/02 01:50

    では使用しても「Javascriptのみでの実装」ですね。正直イベントの発報がめんどうなので使っています。
    で、どこを押しても閉じるのは「※ 下記コードはメニューが開いているかどうかを確認していないため、閉じている時にほかのものをクリックしたらメニューが開きます」を読んでください。

    キャンセル

check解決した方法

-1

再度調べなおしてみます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

-1

再度調べなおしてみます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る