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

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

ただいまの
回答率

87.80%

TOPへ戻るボタンの表示・非表示について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 6,002
退会済みユーザー

退会済みユーザー

 前提・実現したいこと

現在TOPへ戻るボタンの実装をしようとしております。

動きとして実装したい事は、

・スクロールを100pxしたらボタンが表示

・スクロールを一番下まで行った時にはボタンを非表示にして、上にスクロールをした時には再度ボタンを表示させたい

このような動きのボタンの実装をしたいです。

初心者で調べてみても上記それぞれ片方ずつの処理については書いてあるのですが、同時に処理をする時の書き方がわからず困っております。 どうかご教授をいただければと思っております。 

よろしくお願いいたします。

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

下記のプログラムを書いて起こっている事は、

・スクロールを100pxした時にボタンが表示される際に点滅した後に表示される。

・一番下までスクロールした際にはPCブラウザでは非表示になるが、iPhoneのsafariで確認した際に非表示にならない。 一番下から上にスクロールした時に表示されるのは問題なく、上からのスクロール量が100px以下になった時に点滅が起こり表示されたままになってしまう。

 該当のソースコード

<!doctype html>
<html>
<head></head>

<body>
<?php require_once('header.php') ?>

    <section id="MAIN">
        <div class="mainview">
            <div class="main_text"></div>                
            <a href="#about"><span></span></a>                    
        </div><!--end mainview--> 
        <div id="about">
            <div class="title_area"></div>
            <div class="about_cont"></div><!--end about_cont-->
        </div>
        <div id="totop">
            <a href="/"><img src="img/btn_top.png" alt="TOPへ戻る"></a>
        </div><!--end totop-->
    </section><!--end MAIN-->

<?php require_once('footer.php') ?>
</body>
</html>
    $(function() {        
        var topBtn = $('#totop');
        topBtn.hide();

        //スクロールが100に達したらボタン表示
        $(window).scroll(function () {
            if ($(this).scrollTop() > 100) {
                topBtn.fadeIn("slow");
            }
            else {
                topBtn.fadeOut("slow");
            }
        }); 

        $(window).scroll(function(ev) {
            var $window = $(ev.currentTarget),
                height = $window.height(),
                scrollTop = $window.scrollTop(),
                documentHeight = $(document).height();
            if (documentHeight === height + scrollTop) {
                // 一番下のときの処理
                topBtn.fadeOut("slow");
            } else {
                topBtn.fadeIn("slow");
            }
        });        
    });
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • namda

    2018/08/03 11:22

    HTMLのソースも添えてください。

    キャンセル

  • この投稿は削除されました

  • 退会済みユーザー

    退会済みユーザー

    2018/08/03 11:30

    先ほど追加いたしました。 よろしくお願いいたします。

    キャンセル

回答 3

+5

ん〜…もう少しjQueryに関して勉強しないとダメそう。
コードを書くのはあくまでも質問者さん自身で、それ以上はクラウドワークスにでも行けって低評価されちゃうから頑張って。

今回の悪い所は$(window).scroll(fn)topBtn.fadeOut("slow")の挙動をよく知らない事だから、
これに関しては解説していこう。

$(window).scroll(fn)の挙動

結論: 2つ登録したら2つとも実行されるよ。

JSはシングルスレッドで動作するから、一つのJSコードが走っている場合は、他のコードは一切動作出来ない。
でもブラウザってマウスを動かしながらスクロールしたり、同時並行で色んな動作して欲しいよね?

それに対応するために、JSは「イベント駆動」という思想を取り入れてる。
ブラウザはイベントという棚を用意してくれてて、ここにやりたい事を関数として設置してねというルールを設けている。
$(window).scroll(fn)はページ全体のスクロールが行われた時用のイベントにやりたい事を指定する文。

今回の質問文はこの$(window).scroll(fn)を2つ設置してるね。
こういう書き方すると、jQueryは基本的に登録順に逐次実行してくれる。

topBtn.fadeOut("slow")

結論: これは非同期処理なので、JSの実行はこの行では停止されない。

JSはシングルスレッド動作ってのが根本にあるんだけど、
どうやってフェードアウトを実現しているかというと、CSSプロパティのOpacityを0.01刻みにslowなので2秒間全体を使って等間隔で減らすように実装してるんだよ。(なお数字は適当)

しかしJSはシングルスレッドなのでslowの2秒間まるっと動作を止めるわけには行かない。
setTimeout(fn, 17);という機能を使って、17ミリ秒おきに実行してねというお願いを発行しつつ、休み休み実行する。
つまり、topBtn.fadeOut("slow")の行自身の実行は一瞬で終わる。


この2つを組み合わせるとどうなるか?

$(window).scroll(fn)を2つ登録すると、スクロールの度に実行する。
topBtn.fadeOut("slow")は非同期実行の登録処理でしかないので、
この行自体は一瞬で動作を完了し、その後の2秒間は自動的にCSSのOpacity値の変更することになる。

従って、質問文のコードを実行するとtopBtn.fadeOut("slow")topBtn.fadeIn("slow")がほぼ同時に開始されて点滅されているように見える。
質問文の状況に近いんじゃないかな?


じゃあどうすればいいか?
とりあえず$(window).scroll(fn)を一つにまとめて、
if 〜 else if 〜 ifという風に3つの条件分岐を記述するべきだろうね。

質問文からの2つの条件を加味して適当に設定するとこんな感じになりそうだね。

  • ページトップから100pxは非表示
  • ページボトムから100pxは非表示
  • それ以外は表示

・スクロールを一番下まで行った時にはボタンを非表示にして、上にスクロールをした時には再度ボタンを表示させたい

下までスクロールしたらページトップに戻りたいと思うんだけど、
なんでボタン消えちゃうの?UX的にダメじゃね?感が出てる気がする……

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/03 11:39

    細かいご教授ありがとうございます。 まだまだ勉強不足ですね… 頑張って覚えて行こうと思います。 

    自分もなぜ一番下に行った時にボタンを消すのかよく分からないんですが、クライアントさんの方の指示で消して欲しいとの事でしたので… 

    一度教えていただいた条件分岐でやってみたいと思います。 ありがとうございます!

    キャンセル

  • 2018/08/03 12:03

    miyabi-sun さん
    デザインにもよりますが、ページトップボタンがフッターの文字に被ったりで消すことは少ないくないです。
    フッターまで来てページトップボタンが有るとフッター内のリンク導線をクリックしないでトップに戻り離脱しないためにも消すことがあります。

    キャンセル

+2

まずボタンの表示非表示を切り替えるための条件を整理してみるといいかもしれません。
今回の場合3つの状態が存在するのではないでしょうか?
1、スクロール量が100px以下の状態
2、スクロールが一番下にいる状態
3、それ以外の状態

1と2のときは非表示、3のときは表示となると思いますが、
それぞれ
1→2
2→3
3→2
2→1
というふうに状態が変化しますよね。
変化したときに1度だけ、その状態に応じでfadeIn,fadeOutをするとこで解決できそうです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/03 11:17

    早急なお答えありがとうございます! 

    早速条件の方を見直してみて一度やってみたいと思います。

    キャンセル

checkベストアンサー

0

2つ目のwindow.scrollイベントの中身がごちゃごちゃしていたのでまとめてみました!
window.scrollイベントは1つにまとめちゃったほうが良いですよ。

サンプルを作成したのでご確認ください。
動くサンプル

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/03 14:36

    なるほど。 そうですよね。 メニュー分の高さを足したら消えると言うことですよね! 

    なので、
    if ((pageBottom + 100) <= (windowTop + 100)) {
    topBtn.fadeOut("slow");
    }

    と言うことになるのでしょうか?

    キャンセル

  • 2018/08/03 14:40 編集

    それだと結果が変わらなくないですか??
    スマホに関しては実機でデバッグをしながらではないと正確のことは言えません。
    実際にスマホで確認しながらデバッグを進めてみてください。

    キャンセル

  • 2018/08/03 16:10

    細かくありがとうございます! やってみます!

    キャンセル

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

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

関連した質問

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