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

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

ただいまの
回答率

90.04%

横スクロールバーの表示/非表示に合わせて、横スクロールメニューの両端に配置した矢印の表示/非表示を切り替えたい。

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 287

MajinBoo

score 6

前提

横スクロールメニューを作っています。

動作サンプル

スクロールバーの位置が左端にある場合はメニューの右に矢印が表示され、バーの位置が右端にある場合はメニューの左に矢印が表示され、いずれの場合でもない場合は矢印が両方表示します。
また、矢印ボタンを押すとスクロール位置が移動します。

問題点

スクロールバーが表示されない状態(ウインドウサイズが大きい場合)でも、矢印が表示されます。

実現したいこと

スクロールバーが表示されなくなれば、矢印を非表示にしたいです。
また、ウインドウをリサイズした際にスクロールバーが表示されれば、矢印を表示したいです。

該当のソースコード

<body>
  <!-- ボタンエリア表示 -->
  <button id="show">show</button>
  <!-- ボタンエリア -->
  <div id="buttonArea">
    <nav class="menu">
      <!-- 左矢印 -->
      <button class="arrow arrow-left"><i class="fas fa-chevron-left"></i></button>
      <!-- ボタン -->
      <ul class="btn-wrap">
        <li><button class="buttons"><i class="fab fa-html5"></i></button></li>
        <li><label for="css" class="buttons"><i class="fab fa-css3-alt"></i><input type="checkbox" id="css"></label></li>
        <li><button class="buttons"><i class="fab fa-js-square"></i></button></li>
        <li><label for="python" class="buttons"><a id="python"><i class="fab fa-python"></i></a></label></li>
        <li><button class="buttons"><i class="fab fa-php"></i></button></li>
        <li><button class="buttons"><i class="fab fa-java"></i></button></li>
      </ul>
      <!-- 右矢印 -->
      <button class="arrow arrow-right"><i class="fas fa-chevron-right"></i></button>
    </nav>
    <!-- ボタンエリア非表示 -->
    <button id="hide">hide</button>
  </div>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
  <script src="https://kit.fontawesome.com/cb48cdc9db.js"></script>
</body>
html {
    text-align: center;
}

/* ボタン要素のデフォルトのスタイルをリセット */
button {
    background: none;
    border: 0;
    outline: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}

/* ボタンエリアの表示・非表示ボタン */
#show {
    border: 1px solid black;
    cursor: pointer;
    margin: 3%;
}
#hide {
    border: 1px solid black;
    cursor: pointer;
    margin: 3%;
}

/* メニュー全体 */
#buttonArea {
    display: none;
}
.menu {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* 矢印 */
.arrow {
    cursor: pointer;
}
.arrow-left {
    margin-right: 10px;
}
.arrow-right {
    margin-left: 10px;
}
.arrow .fas {
    font-size: 30px;
}

/* ボタンを囲む用 */
.btn-wrap {
    display: flex;
    max-width: 50%;
    overflow-x: auto;
    overflow-y: hidden;
    border: 1px solid #ccc;
}
.buttons {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 70px;
    height: 70px;
    margin: 5px;
    border: 5px solid #000;
    background-color: #fff;
    cursor: pointer;
}
.buttons .fab, .buttons .fas {
    font-size: 50px;
}
.buttons a {
    line-height: 0;
}
#css {
    display: none;
}
// ボタンエリア表示・非表示ボタン
$("#show").on("click", function () {
    $("#buttonArea").show();
    $(".btn-wrap").scrollLeft(0);
    $(".arrow-left").css("visibility", "hidden");
});
$("#hide").on("click", function () {
    $("#buttonArea").hide();
});

// 矢印ボタン ドラッグ 表示/非表示
$(".btn-wrap").on("scroll", function () {
    var scrollPosition = $(".btn-wrap").scrollLeft();
    var maxPostion = $('.btn-wrap').get(0).scrollWidth - $('.btn-wrap').get(0).clientWidth;
    if (scrollPosition === 0) {
        $(".arrow-left").css("visibility", "hidden");
        $(".arrow-right").css("visibility", "visible");
    } else if (scrollPosition === maxPostion) {
        $(".arrow-right").css("visibility", "hidden");
        $(".arrow-left").css("visibility", "visible");
    } else if (scrollPosition > 0 && scrollPosition < maxPostion) {
        $(".arrow").css("visibility", "visible");
    };
});

// 矢印ボタン 押下 表示/非表示
$(".arrow-left").on("click", function () {
    var scrollPosition = $(".btn-wrap").scrollLeft();
    if (scrollPosition > 0) {
        $(".btn-wrap").scrollLeft(scrollPosition - 40);
        return;
    };
    $(".btn-wrap").scrollLeft(0);
});
$(".arrow-right").on("click", function () {
    var scrollPosition = $(".btn-wrap").scrollLeft();
    var maxPostion = $('.btn-wrap').get(0).scrollWidth - $('.btn-wrap').get(0).clientWidth;
    if (scrollPosition < maxPostion) {
        $(".btn-wrap").scrollLeft(scrollPosition + 40);
        return;
    };
    $(".btn-wrap").scrollLeft(maxPostion);
});

試したこと

overflow:auto のスクロールバーの表示/非表示を確認する
上記記事を参考にスクロールバーの有無をチェックするプラグインを作成し、ウインドウを読み込んだ際とウインドウがリサイズされた際のイベントとして、下記のように記述しました。

jQuery.fn.hasScrollBar = function () {
    return this.get(0) ? this.get(0).scrollWidth > this.innerWidth() : false;
};

$(window).on("ready", function () {
    if (!$('.btn-wrap').hasScrollBar()) { // スクロールバーがなければ、矢印を非表示
        $(".arrow-left").css("visibility", "hidden");
        $(".arrow-right").css("visibility", "hidden");
    };
});
$(window).on("resize", function () {
    if (!$('.btn-wrap').hasScrollBar()) {
        $(".arrow-left").css("visibility", "hidden");
        $(".arrow-right").css("visibility", "hidden");
    };
});


結果は変わりませんでした。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • x_x

    2019/09/02 17:54

    show ボタンを押した後には処理していませんが、そのことを言っています?

    キャンセル

  • MajinBoo

    2019/09/02 23:56

    showボタンを押したあとはボタンエリアを表示しスクロールバーを左端にセットし、左矢印を非表示する処理をしています。試したことのコードは該当のソースコードのコードを省略した形で書いています。

    キャンセル

回答 1

checkベストアンサー

0

状態としては
・両方の矢印が表示されていない
・左矢印が表示されていて右矢印が表示されていない
・右矢印が表示されていて左矢印が表示されていない
・両方の矢印が表示されている
の四つが考えられます。

確かにスクロール直後であればスクロールバーが存在しているので「両方が表示されていない」というのはないのですが、同様の処理をあちこちに書くとわかりにくくなるので一か所にまとめておいたらどうでしょうか?
以下のような関数を表示時、リサイズ時、スクロール時に呼び出すようにします。

function fixArrowVisibility() {
    var scrollPosition = $(".btn-wrap").scrollLeft();
    var maxPostion = $('.btn-wrap').get(0).scrollWidth - $('.btn-wrap').get(0).clientWidth;
    var arrowLeftVisibility = 'visible';
    var arrowRightVisibility = 'visible';

    if (scrollPosition === 0) {
        arrowLeftVisibility = 'hidden';
    }

    if (scrollPosition === maxPostion) {
        arrowRightVisibility = 'hidden';
    }

    $(".arrow-left").css("visibility", arrowLeftVisibility);
    $(".arrow-right").css("visibility", arrowRightVisibility);
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/09/03 12:20

    希望通りの機能を実装できた上にコードを簡略化できました。本当にありがとうございました。

    キャンセル

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

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • JavaScriptに関する質問
  • 横スクロールバーの表示/非表示に合わせて、横スクロールメニューの両端に配置した矢印の表示/非表示を切り替えたい。