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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

1回答

344閲覧

ページ内のリンク先セクションへスクロールする際、セクションの少し手前でスクロールを止めたい

thayamizu

総合スコア7

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2020/07/05 15:40

下記smooth scrollingのjQueryでhtml上のaタグのリンク先セクション(同一ページ内)にクリックした時にスクロールするようにしたのですが、下記のままだとセクションの見出しと上部に固定しているナビゲーションバーがかぶってしまいました。
下記コードのどこかにoffsetを指定して、リンク先セクションにスクロールする際にナビゲーションバー分(50px)手前でスクロールを止めたかったのですが、うまくいきませんでした。
どのようにすればセクションの手前指定ができるのでしょうか?

javascript

1$('a[href*="#"]') 2 // Remove links that don't actually link to anything 3 .not('[href="#"]') 4 .not('[href="#0"]') 5 .click(function (event) { 6 // On-page links 7 if ( 8 location.pathname.replace(/^//, "") == 9 this.pathname.replace(/^//, "") && 10 location.hostname == this.hostname 11 ) { 12 // Figure out element to scroll to 13 var target = $(this.hash); 14 target = target.length 15 ? target 16 : $("[name=" + this.hash.slice(1) + "]"); 17 // Does a scroll target exist? 18 if (target.length) { 19 // Only prevent default if animation is actually gonna happen 20 event.preventDefault(); 21 $("html, body").animate( 22 { 23 scrollTop: target.offset().top, 24 }, 25 1000, 26 27 function () { 28 // Callback after animation 29 // Must change focus! 30 var $target = $(target); 31 $target.focus(); 32 if ($target.is(":focus")) { 33 // Checking if the target was focused 34 return false; 35 } else { 36 $target.attr("tabindex", "-1"); // Adding tabindex for elements not focusable 37 $target.focus(); // Set focus again 38 } 39 } 40 ); 41 } 42 } 43 });

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

HTMLが提示されてないので仮のクラス名を使ってます。

全ソース公開を受けてソースコードを差し替えました

jQueryプラグインSTICKY NAVIGATIONを使っているんですね。

プラグインを使用している場合はそのことを明記し、プラグインの公式へのリンクも記述してください。またスクリプトの一部だけではなく、全文を公開してください。おかげでプラグインあるのかー。ちゃんと問題ないかプラグインに影響を与えていないかテストしてて回答が遅れました

JavaScript

1$(function () { 2 /*FOR STICKY NAVIGATION*/ 3 var offsetY; 4 if (!$("nav").hasClass("sticky")) { 5 offsetY = $("nav").addClass("sticky").outerHeight(); 6 $("nav").removeClass("sticky"); 7 } else { 8 offsetY = $("nav").outerHeight(); 9 } 10 11 $(".js--section-features").waypoint( 12 function (direction) { 13 if (direction == "down") { 14 $("nav").addClass("sticky"); 15 } else { 16 $("nav").removeClass("sticky"); 17 } 18 }, 19 { 20 offset: offsetY, 21 } 22 ); 23 $(".js--scroll-to-plans").click(function () { 24 $("html,body").animate( 25 { 26 scrollTop: $(".js--section-plans").offset().top - offsetY, 27 }, 28 1000 29 ); 30 }); 31 32 $(".js--scroll-to-start").click(function () { 33 $("html,body").animate( 34 { 35 scrollTop: $(".js--section-features").offset().top - offsetY, 36 }, 37 1000 38 ); 39 }); 40 41 $('a[href*="#"]') 42 // Remove links that don't actually link to anything 43 .not('[href="#"]') 44 .not('[href="#0"]') 45 .click(function (event) { 46 // On-page links 47 if ( 48 location.pathname.replace(/^//, "") == 49 this.pathname.replace(/^//, "") && 50 location.hostname == this.hostname 51 ) { 52 // Figure out element to scroll to 53 var target = $(this.hash); //ここでjQueryオブジェクトに変換済み 54 target = target.length 55 ? target 56 : $("[name=" + this.hash.slice(1) + "]"); 57 // Does a scroll target exist? 58 if (target.length) { 59 // Only prevent default if animation is actually gonna happen 60 //event.preventDefault(); 61 62 $("html,body").animate( 63 { 64 scrollTop: target.offset().top - offsetY, 65 }, 66 1000, 67 function () { 68 // Callback after animation 69 // Must change focus! 70 var oldScroll = $(window).scrollTop(); 71 $(window).one('scroll', function() { //focus()の直前に一度だけ機能するscrollのイベントリスナを設定 72 $(window).scrollTop(oldScroll); //focus()によるスクロールを一度だけ上書きして無効化する。 73 }); 74 75 target.focus(); //targetは既にjQueryオブジェクトになっているから変換は不要 76 if (target.is(":focus")) { 77 // Checking if the target was focused 78 return false; 79 } else { 80 target.attr("tabindex", "-1"); // Adding tabindex for elements not focusable 81 var oldScroll = $(window).scrollTop(); 82 $(window).one('scroll', function() { //focus()の直前に一度だけ機能するscrollのイベントリスナを設定 83 $(window).scrollTop(oldScroll); //focus()によるスクロールを一度だけ上書きして無効化する。 84 }); 85 target.focus(); // Set focus again 86 } 87 } 88 ); 89 } 90 } 91 }); 92 93 $(".js--wp-1").waypoint( 94 function (direction) { 95 $(".js--wp-1").addClass("animated animate__fadeIn"); 96 }, 97 { 98 offset: "50%", 99 } 100 ); 101 102 $(".js--wp-2").waypoint( 103 function (direction) { 104 $(".js--wp-2").addClass("animated animate__fadeInUp"); 105 }, 106 { 107 offset: "50%", 108 } 109 ); 110 111 $(".js--wp-3").waypoint( 112 function (direction) { 113 $(".js--wp-3").addClass("animated animate__fadeIn"); 114 }, 115 { 116 offset: "50%", 117 } 118 ); 119 120 $(".js--wp-4").waypoint( 121 function (direction) { 122 $(".js--wp-4").addClass("animated animate__pulse"); 123 }, 124 { 125 offset: "50%", 126 } 127 ); 128 129 $(".js--nav-icon").click(function () { 130 var nav = $(".js--main-nav"); 131 var icon = $(".js--nav-icon i"); 132 133 nav.slideToggle(200); 134 135 if (icon.hasClass("ion-navicon-round")) { 136 icon.addClass("ion-close-round"); 137 icon.removeClass("ion-navicon-round"); 138 } else { 139 icon.addClass("ion-navicon-round"); 140 icon.removeClass("ion-close-round"); 141 } 142 }); 143 }); 144 145 // フォーカス系のイベントでのスクロール処理をキャンセルする。 146 // 147 // firefox以外のブラウザは要素がフォーカスされた場合、フォームのテキストエリアなど入力がスムーズに 148 // 出来るように、その要素をスクロールさせる。(正常な動き)その後その要素に対してselectが 149 // 発生します。 150 // firefoxはバグっててスクロールせずにフォーカスだけがあたる。 151 // 152 // コード内で要素.focus()する場合は、この解決策でも回避できない場合があります 153 // これでもたまにスクロールすることがあり、もう一度クリックすれば直ります。 154 // ブラウザ側の実装の問題なのでこれ以上は対処できません。 155 // 156 // 問題が無ければ、要素.focus()ではなく、要素.select()を検討してみて下さい 157 // そうすれば、スクロールの問題は解決するはずです。 158 $('section').bind('focusin focus', function(event){ 159 event.preventDefault(); 160 });

firefoxのみ正しく動いて見えたのはfirefoxにバグがあってスクロールしなかったからで
firefox以外のブラウザの動作が正常動作です。
動作確認してみたところ、IEはバグっててダメでした、edge(WEBから落としてきた最新版のedge),chrome,firefoxでは一応問題ありませんでしたが、chromeでまれにスクロールする事がありましたが再度クリックで直ります。
その他についてはソースにコメントを入れてあるので参照してください。

はぁ、プラグインもテストしてて予想外に疲れた・・・

追記:更なる改良でほぼfocus()のスクロールをIE以外で無効化できましたので、再再度ソースを差し替えました

focus()の直前に以下のコードを入れておくと最後に追加しているイベントハンドラと合わせて
ほぼ無効化できました。
focus()の直前に以下のコードを入れ込む

javascript

1var oldScroll = $(window).scrollTop(); 2$(window).one('scroll', function() { //focus()の直前に一度だけ機能するscrollのイベントリスナを設定 3 $(window).scrollTop(oldScroll); //focus()によるスクロールを一度だけ上書きして無効化する。 4});

このコードと、最後に追加した'focusin focus'イベントリスナの2重のガードで、IE以外は完全に動作が正常化されました。

投稿2020/07/05 16:12

編集2020/07/08 08:55
nekora

総合スコア501

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thayamizu

2020/07/06 00:45

ディバイスによって高さが違う時の高さ取得方法まで教えて頂きありがとうございます。 この方法で一瞬だけナビゲーションバー高さ分手前でスクロールが止まるのですが、次の瞬間、リンク先のトップに移動してしまい、結局ナビゲーションバーがリンク先セクションの見出しとかぶってしまいました。 event.preventDefault();をありにしても基本的には同じでしたが、これをありにした場合は、もう一度ナビゲーションバーの同じリンクをクリックすると、指定したoffsetY分だけ手前にスクロールで戻って止まりました。 最初にクリックした時から指定したoffsetY分だけ手前でスクロールが止まって欲しいのですが、解決策はありますでしょうか?
nekora

2020/07/06 07:27 編集

質問は編集、追記できます。HTMLとCSSも提示いただかないと、これ以上回答できません。HTML、CSSも開示ください。 そうすれば、調査して答えを出せると思います。
thayamizu

2020/07/06 16:38

ご指摘ありがとうございます。 下記のURLなのですがfirefoxで開いた時だけアドバイスいただいた方法(event.preventDefault();ありでもなしでも)で綺麗に表示されました。 IE/Chrome/Microsoft Edge/safariではうまくいっていないように思います。(一瞬手前で止まるがすぐに下に下がる) event.preventDefault();を無しにすると2回目にナビゲーションリンクをクリックした時はちゃんと手前で止まるブラウザもありました。(すみません。09:45に返信した内容と逆でした。) https://omnifood.work/ ※section内の見出しはpaddingで調整してあるので、offset指定無しでもナビゲーションバーと被らなくなっていますが、ナビゲーションバーをsection手前で止めたいのは変わりありません。 ソースがたくさんあり、質問の方でどのように開示したらよいか分からなかったのでURLで開示させて頂きました。
nekora

2020/07/08 03:53

スクロール対処版のソースコードに差し替えました。チェックしてみてください。 なぜこうなるのか、何が問題なのかなど、回答とソースコードに記載しました。
nekora

2020/07/08 08:58

ソースコードの更なる改良でIE以外はほぼ正常に動作するようになりました。 このコードで動作確認してみてください。
thayamizu

2020/07/09 01:47

ありがとうございます! 確認してみたところ、やりたかったことが実現できました! プラグインがあると影響を与えることも知らずにお手数おかけしてすみませんでした。 firefoxが正常に見えていたのはfirefoxのバグだとは思ってもおりませんでした。丁寧に教えて頂き本当にありがとうございます。勉強になりました!
nekora

2020/07/09 03:18

ただこれだけやっても100%じゃないんですよ>< リンクを連打されるとoneのイベントリスナのつけ外しが間に合わなくて スクロールすることがあります。 が、特殊なケースだとおもうので、ほぼこれでいいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問