スティッキーサイドバー:下にスクロールすると下に、上にスクロールすると上に貼り付けます


94

スティッキーサイドバーの問題の解決策を探していました。私はそれをどのように行動させたいかについて具体的な考えを持っています。事実上、下にスクロールすると下にくっつき、上にスクロールするとすぐに上にくっつき、滑らかな動き(ジャンプなし)になります。私が達成しようとしていることの例を見つけることができないので、私はポイントをより明確に説明することを望む画像を作成しました:

スティッキーサイドバー:下にスクロールすると下に、上にスクロールすると上に貼り付けます

  1. サイドバーはヘッダーの下にあります。
  2. 下にスクロールしても、サイドバーはページのコンテンツと同じ高さのままなので、サイドバーとコンテンツの両方をスクロールできます。
  3. サイドバーの下部に到達すると、サイドバーはビューポートの下部に固定されます(ほとんどのプラグインは上部にのみ固定できますが、下部に固定できるプラグインの中には両方を使用できないものもあります)。
  4. 下部に到達すると、サイドバーはフッターの上に配置されます。
  5. 上にスクロールしても、サイドバーはコンテンツと同じ高さに保たれるため、コンテンツとサイドバーをもう一度スクロールできます。
  6. サイドバーの上部に到達すると、サイドバーはビューポートの上部に固定されます。
  7. 上部に到達すると、サイドバーがヘッダーの下に戻ります。

これで十分な情報になるといいのですが。プラグイン/スクリプトをテストするためにjsfiddleを作成しましたが、この質問のためにリセットしました:http//jsfiddle.net/jslucas/yr9gV/2/ .

回答:


25

とても素敵で実例となる画像に+1します。

古い質問だとは思いますが、forum.jquery.comにあなたが投稿した同じ質問とそこにある1つの回答(by @ tucker973)を何気なく見つけ、これを作成するための1つの素晴らしいライブラリを提案し、ここで共有したいと思いました。

@leafoではスティッキーキットと呼ばれています

ここに、私が準備した非常に基本的な例のコードと、結果を確認するための実用的なデモがあります。

もちろん、すべてのクレジットはプラグインの作成者に送られます。ここでは、この例を示しただけです。私はあなたが求めていたのと同じ結果を達成する必要があり、このプラグインが非常に役立つことがわかりました。


私はあなたが提案するようにこの小さなプラグインを使用しますが、それが上にくっついた後に幅が変わります。どうすれば変更できませんか?
vijayrana

こんにちは@gmo!同じものを探していますが、スクロールバーがビューポートよりも長い場合は機能しません(上にスクロールしても上に固執しません)...
IgorLaszlo19年

13

素晴らしいグラフィックをありがとう。私もこの課題の解決策を探していました!

残念ながら、ここに投稿された他の回答は、サイドバーをスムーズにスクロールバックする機能を規定する要件#5に対応していません。

すべての要件を実装するフィドルを作成しました:http//jsfiddle.net/bN4qu/5/

実装する必要のあるコアロジックは次のとおりです。

If scrolling up OR the element is shorter than viewport Then
  Set top of element to top of viewport If scrolled above top of element
If scrolling down then
  Set bottom of element at bottom of viewport If scrolled past bottom of element

フィドルでは、CSS3変換を使用してターゲット要素を移動しているため、IE <9などでは機能しません。ただし、別のアプローチを使用する場合のロジックは適切です。

また、スティッキーサイドバーの背景がグラデーションになるようにフィドルを変更しました。これは、適切な動作が示されていることを示すのに役立ちます。

これが誰かに役立つことを願っています!


2
答えを探している人にとって、これはトラビスによるもので、私がこれまでに見つけた中で最も完璧です。ありがとう。
marcovega 2015

素晴らしい試みでした。基本的には、これをドロップしたときに機能しました。これは、他のプラグインで言うことができる以上のことです:)パフォーマンスは大ヒットしましたが、ネイティブでないスティッキー実装ではほぼ当然だと思います。
jClark 2016

これは素晴らしい出発点でした!$.css関数をaでラップし、requestAnimationFramevue / reactなどの最新のフロントエンドフレームワークで使用するためのdestroy / unbind関数を追加しました。その後、パフォーマンスはまったく問題になりません。
クリストフ

@Cristophe Maroisjsfiddleの例を教えてください。
DuArme

ありがとう、しかしこのコードはビューポート(ビューポートの高さ)より短い小さなサイドバーでは機能しません
Seyed AbbasSeyedi19年

12

これを実装する方法の例を次に示します。

JavaScript:

$(function() {

var $window = $(window);
var lastScrollTop = $window.scrollTop();
var wasScrollingDown = true;

var $sidebar = $("#sidebar");
if ($sidebar.length > 0) {

    var initialSidebarTop = $sidebar.position().top;

    $window.scroll(function(event) {

        var windowHeight = $window.height();
        var sidebarHeight = $sidebar.outerHeight();

        var scrollTop = $window.scrollTop();
        var scrollBottom = scrollTop + windowHeight;

        var sidebarTop = $sidebar.position().top;
        var sidebarBottom = sidebarTop + sidebarHeight;

        var heightDelta = Math.abs(windowHeight - sidebarHeight);
        var scrollDelta = lastScrollTop - scrollTop;

        var isScrollingDown = (scrollTop > lastScrollTop);
        var isWindowLarger = (windowHeight > sidebarHeight);

        if ((isWindowLarger && scrollTop > initialSidebarTop) || (!isWindowLarger && scrollTop > initialSidebarTop + heightDelta)) {
            $sidebar.addClass('fixed');
        } else if (!isScrollingDown && scrollTop <= initialSidebarTop) {
            $sidebar.removeClass('fixed');
        }

        var dragBottomDown = (sidebarBottom <= scrollBottom && isScrollingDown);
        var dragTopUp = (sidebarTop >= scrollTop && !isScrollingDown);

        if (dragBottomDown) {
            if (isWindowLarger) {
                $sidebar.css('top', 0);
            } else {
                $sidebar.css('top', -heightDelta);
            }
        } else if (dragTopUp) {
            $sidebar.css('top', 0);
        } else if ($sidebar.hasClass('fixed')) {
            var currentTop = parseInt($sidebar.css('top'), 10);

            var minTop = -heightDelta;
            var scrolledTop = currentTop + scrollDelta;

            var isPageAtBottom = (scrollTop + windowHeight >= $(document).height());
            var newTop = (isPageAtBottom) ? minTop : scrolledTop;

            $sidebar.css('top', newTop);
        }

        lastScrollTop = scrollTop;
        wasScrollingDown = isScrollingDown;
    });
}
});

CSS:

#sidebar {
  width: 180px;
  padding: 10px;
  background: red;
  float: right;
}

.fixed {
  position: fixed;
  right: 50%;
  margin-right: -50%;
}

デモ: http //jsfiddle.net/ryanmaxwell/25QaE/

これはすべてのシナリオで期待どおりに機能し、IEでも十分にサポートされています。


この回答を参照して、stackoverflow.com
questions / 28428327

@ AnoopNaik-それは私が探しているものとほぼ同じです... sticky-kitは、ビューポートより長いサイドバーでは機能しません。あなたの機能です。しかし、私は反対のことを望みます:私が下にスクロールすると、それは上にくっつき、上にスクロールすると、それは下にくっつきます...フィドルのその小さな変化で私を喜ばせるのを手伝ってくれませんか?
IgorLaszlo19年

1
@IgorLaszlo確かに、いつかはあなたを更新します...
AnoopNaik19年

これは私の問題も説明しています:「位置:スティッキーの要素が「スタック」していてビューポートより長い場合、コンテナの一番下までスクロールした後にのみコンテンツを表示できます。「スタック」要素をスクロールするとかっこいいでしょうドキュメントを使用して停止し、下端に到達すると、ユーザーがスクロールバックすると、同じことが再び発生しますが、逆になります。」-同じ問題(持っている別の人によって書かれたstackoverflow.com/questions/47618271/...を
イゴール・ラズロ

@Anoop Naik!あなたの努力に感謝しますが、それを許してください、私は私の問題を解決するためにスティッキーjqueryプラグインを見つけました:abouolia.github.io/sticky-sidebarもう一度ありがとう!
イゴール・ラズロ

0

私はまったく同じものを探していました。どうやら私はグラフィックで同様の質問を見つけるためだけにいくつかのあいまいな用語を検索する必要がありました。それがまさに私が探していたものであることがわかりました。プラグインが見つからなかったので、自分で作ることにしました。うまくいけば、誰かがこれを見て、それを洗練するでしょう。

これが私が使っている速くて汚いサンプルhtmlです。

<div id="main">
    <div class="col-1">
    </div>
    <div class="col-2">
        <div class="side-wrapper">
            sidebar content
        </div>
    </div>
</div>

これが私が作ったjQueryです:

var lastScrollPos = $(window).scrollTop();
var originalPos = $('.side-wrapper').offset().top;
if ($('.col-2').css('float') != 'none') {
    $(window).scroll(function(){
        var rectbtfadPos = $('.rectbtfad').offset().top + $('.rectbtfad').height();
        // scroll up direction
        if ( lastScrollPos > $(window).scrollTop() ) {
            // unstick if scrolling the opposite direction so content will scroll with user
            if ($('.side-wrapper').css('position') == 'fixed') {
                $('.side-wrapper').css({
                    'position': 'absolute',
                    'top': $('.side-wrapper').offset().top + 'px',
                    'bottom': 'auto'
                });
            } 
            // if has reached the original position, return to relative positioning
            if ( ($(window).scrollTop() + $('#masthead').height()) < originalPos ) {
                $('.side-wrapper').css({
                    'position': 'relative',
                    'top': 'auto',
                    'bottom': 'auto'
                });
            } 
            // sticky to top if scroll past top of sidebar
            else if ( ($(window).scrollTop() + $('#masthead').height()) < $('.side-wrapper').offset().top && $('.side-wrapper').css('position') == 'absolute' ) {
                $('.side-wrapper').css({
                    'position': 'fixed',
                    'top': 15 + $('#masthead').height() + 'px', // padding to compensate for sticky header
                    'bottom': 'auto'
                });
            }
        } 
        // scroll down
        else {
            // unstick if scrolling the opposite direction so content will scroll with user
            if ($('.side-wrapper').css('position') == 'fixed') {
                $('.side-wrapper').css({
                    'position': 'absolute',
                    'top': $('.side-wrapper').offset().top + 'px',
                    'bottom': 'auto'
                });
            } 
            // check if rectbtfad (bottom most element) has reached the bottom
            if ( ($(window).scrollTop() + $(window).height()) > rectbtfadPos && $('.side-wrapper').css('position') != 'fixed' ) {
                $('.side-wrapper').css({
                    'width': $('.col-2').width(),
                    'position': 'fixed',
                    'bottom': '0',
                    'top': 'auto'
                });
            }
        }
        // set last scroll position to determine if scrolling up or down
        lastScrollPos = $(window).scrollTop();

    });
}

いくつかの注意:

  • .rectbtfadは私のサイドバーの一番下の要素です
  • #mastheadの高さはスティッキーヘッダーなので、それを補正する必要があるため、使用しています。
  • レスポンシブデザインを使用していて、小さい画面でこれをアクティブにしたくないので、col-2floatのチェックがあります

誰かがこれをもう少し洗練することができれば、それは素晴らしいことです。


0
function fixMe(id) {
    var e = $(id);
    var lastScrollTop = 0;
    var firstOffset = e.offset().top;
    var lastA = e.offset().top;
    var isFixed = false;
    $(window).scroll(function(event){
        if (isFixed) {
            return;
        }
        var a = e.offset().top;
        var b = e.height();
        var c = $(window).height();
        var d = $(window).scrollTop();
        if (b <= c - a) {
            e.css({position: "fixed"});
            isFixed = true;
            return;
        }           
        if (d > lastScrollTop){ // scroll down
            if (e.css("position") != "fixed" && c + d >= a + b) {
                e.css({position: "fixed", bottom: 0, top: "auto"});
            }
            if (a - d >= firstOffset) {
                e.css({position: "absolute", bottom: "auto", top: lastA});
            }
        } else { // scroll up
            if (a - d >= firstOffset) {
                if (e.css("position") != "fixed") {
                    e.css({position: "fixed", bottom: "auto", top: firstOffset});
                }
            } else {
                if (e.css("position") != "absolute") {
                    e.css({position: "absolute", bottom: "auto", top: lastA});
                }               
            }
        }
        lastScrollTop = d;
        lastA = a;
    });
}

fixMe("#stick");

実例: https //jsfiddle.net/L7xoopst/6/


少し説明を追加しますか?
haveNoDisplayName 2015

スティッキーアイテム内の高さを更新すると、いくつかの問題が発生します
Callam 2015年

0

Wordpressリポジトリには、WP StickySidebarとして知られる比較的未知のプラグインがあります。プラグインはあなたが望んでいたことを正確に実行します(スティッキーサイドバー:下にスクロールすると下に、上にスクロールすると上に固執します)WPスティッキーサイドバーWordpressリポジトリリンク:https//wordpress.org/plugins/mystickysidebar/


情報をありがとう!完璧に動作しました。プラグインの注目画像の動作図のグラフィックが同じであるのはおかしいです:)
Oksana Romaniv 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.