実現したいこと
モバイルサイズの時、ハンバーガーボタンをクリックすることでドロワーメニューの開閉をしています。
ドロワーメニューが開いている際はサイト全体が現在のスクロール位置で固定され、閉じた時に解除されるようにしています。
またスムーススクロールを実装し、ページ内リンクをクリックした際に該当箇所にスクロールするようにしています。
モバイルサイズ時には、ページ内リンクをクリックした際、ドロワーメニューが閉じ、サイトの固定が解除され、目的の位置までスクロールするようにしたいです。
発生している問題・分からないこと
基本的には動いているのですが、モバイルサイズ時にページ内リンクをクリックした際のスムーススクロールの挙動が怪しいです。
全くスクロールをしていない状態では正常に動くのですが、中途半端にスクロールした状態や該当箇所より下にスクロールした状態だと、スムーススクロールで移動する位置がTOPになったり、画面の中央あたりに移動先が来ていたりと、挙動がおかしくなります。
エラーメッセージ
error
1エラーメッセージは出ていません。
該当のソースコード
HTML
1<header> 2 ヘッダー 3 <nav> 4 <ul class="nav_glb"> 5 <li><a href="index.html"><span>ホーム</span></a></li> 6 <li><a href="#products"><span>事業内容</span></a></li> 7 <li><a href="index.html"><span>会社概要</span></a></li> 8 <li><a href="index.html"><span>拠点情報</span></a></li> 9 <li><a href="index.html"><span>採用情報</span></a></li> 10 <li><a href="index.html"><span>よくある質問</span></a></li> 11 </ul> 12 </nav> 13 <button class="trigger"><span></span></button> 14 <div class="cover_layer"></div> 15 </header> 16 17 <div class="kv"> 18 19 </div> 20 <main class="inner"> 21 22 <h2 id="products">事業内容</h2> 23 <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> 24 </main>
CSS
1body { 2 width: 100%; 3} 4header { 5 position: fixed; 6 top: 0; 7 left: 0; 8 width: 100%; 9 min-height: 2.75rem; 10 background: rgba(0,0,0,.6); 11 transition: .3s; 12 z-index: 100; 13} 14header.change { 15 background: rgba(0,0,0,0); 16 border-bottom: 1px solid #000; 17} 18 19@media (width < 768px ) {/*sp only*/ 20 .trigger { 21 position: fixed; 22 top: 0; 23 right: 0; 24 width: 2.75rem; 25 height: 2.75rem; 26 display: flex; 27 flex-direction: column; 28 justify-content: center; 29 align-items: center; 30 z-index: 1300; 31 } 32 nav { 33 position: fixed; 34 width: 250px; 35 height: 100vh; 36 top: 0; 37 right: -250px; 38 z-index: 1200; 39 background: #fff; 40 transition: .3s; 41 } 42 nav.open { 43 right: 0; 44 } 45 nav .nav_glb { 46 margin-top: 2.75rem; 47 border-top: solid 1px #ccc; 48 } 49 nav .nav_glb li { 50 border-bottom: solid 1px #ccc; 51 } 52 nav .nav_glb li a { 53 display: block; 54 padding: 1rem; 55 } 56 nav .nav_glb li a:hover, 57 nav .nav_glb li a:active { 58 background: rgba(90, 79, 57, 0.2); 59 } 60 .cover_layer { 61 position: fixed; 62 width: 100%; 63 height: 100vh; 64 top: 0; 65 left: 0; 66 z-index: 1100; 67 background: rgba(0,0,0,0); 68 transition: .3s; 69 pointer-events: none; 70 } 71 .cover_layer.open { 72 background: rgba(0,0,0, .7); 73 pointer-events: auto; 74 } 75} 76@media (768px <= width) {/*pc only*/ 77 .trigger,.cover_layer { 78 display: none; 79 } 80 nav { 81 min-height: 2.75rem; 82 } 83 nav .nav_glb { 84 display: flex; 85 height: 2.75rem; 86 } 87 nav .nav_glb li { 88 flex: 1 1 0; 89 position: relative; 90 } 91 nav .nav_glb li a { 92 width: 100%; 93 height: 2.75rem; 94 display: flex; 95 justify-content: center; 96 align-items: center; 97 color: #fff; 98 position: relative; 99 } 100 nav .nav_glb li a:hover { 101 background: #666; 102 } 103} 104.kv { 105 width: 100%; 106 height: 100vh; 107 background: #ccc; 108}
jQuery
1//スライドメニュー 2$(function () { 3 let state = false; // メニューの開閉状態を管理するフラグ 4 let scrollpos; // スクロール位置を保持する変数 5 const change = $('.trigger, nav, .cover_layer'); // メニューのトグル要素 6 7 // メニューのトグル要素がクリックされた時の処理 8 $('.trigger, .cover_layer').on('click', function () { 9 change.toggleClass('open'); // メニューの表示/非表示を切り替える 10 if (state === false) { // メニューが開かれた場合 11 scrollpos = $(window).scrollTop(); // 現在のスクロール位置を取得 12 $('body').css({ 13 position: 'fixed', 14 top: -scrollpos 15 }); // スクロール位置を固定し、ページの位置を保持 16 state = true; // フラグをtrueに設定 17 } else { // メニューが閉じられた場合 18 $('body').attr('style', ''); // スクロール位置の固定を解除 19 window.scrollTo(0, scrollpos); // 元のスクロール位置に戻す 20 state = false; // フラグをfalseに設定 21 } 22 }); 23 24 // ウィンドウの読み込みやリサイズ時に実行する処理 25 $(window).on('load resize', function () { 26 let winW = $(window).width(); // ウィンドウの幅を取得 27 let devW = 768; // スマートフォンサイズの幅 28 if (winW >= devW) { // ウィンドウ幅がスマートフォンサイズより大きい場合 29 if (change.hasClass('open')) { 30 change.removeClass('open'); 31 $('body').attr('style', ''); 32 window.scrollTo(0, scrollpos); 33 state = false; 34 } 35 } 36 }); 37 38 // ページ内リンクがクリックされた時の処理 39 $('a[href^="#"]').on('click', function () { 40 const adjust = $('header').outerHeight(); // ヘッダーの高さを取得 41 const speed = 400; // スクロール速度 42 const href = $(this).attr("href"); // クリックされたリンクのhref属性を取得 43 const target = $(href == "#" || href == "" ? 'html' : href); // スクロール先の要素を取得 44 const position = target.offset().top - adjust; // スクロール位置を計算 45 change.removeClass('open'); // メニューを閉じる 46 $('body').attr('style', ''); // スクロール位置の固定を解除 47 state = false; // フラグをfalseに設定 48 $('body,html').animate({scrollTop: position}, speed, 'swing'); // スムーススクロールを実行 49 return false; // リンクのデフォルト動作を無効化 50 }); 51}); 52 53
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
どうも現在地を変数に保存して、メニューを閉じた時に現在地まで移動する部分とバッティングしているせいっぽいと思うのですが、解決策がわかりませんでした。
現在地を固定→アコーディオンを開いてナビゲーション内でスクロール→ページ内リンクをクリックの辺りが悪影響を及ぼしている気がします。
補足
特になし

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/02/20 06:57