web-dev-qa-db-ja.com

固定サイドバー:下にスクロールすると下に、上にスクロールすると上に固定

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

Sticky sidebar: stick to bottom when scrolling down, top when scrolling up

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

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

71
andbamnan

+ 1とても素敵でイラスト入りの画像に。

私はそれが古い質問であることを知っていますが、あなたが forum.jquery.com に投稿した同じ質問を偶然見つけました。 (by @ tucker973)、これを作成するニースライブラリを提案し、ここで共有したいと考えました。

sticky-kitby@ leafo

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

/*!
 * Sticky-kit
 * A jQuery plugin for making smart sticky elements
 *
 * Source: http://leafo.net/sticky-kit/
 */

$(function() {
  $(".sidebar").stick_in_parent({
    offset_top: 10
  });
});
* {
  font-size: 10px;
  color: #333;
  box-sizing: border-box;
}
.wrapper,
.header,
.main,
.footer {
  padding: 10px;
  position: relative;
}
.wrapper {
  border: 1px solid #333;
  background-color: #f5f5f5;
  padding: 10px;
}
.header {
  background-color: #6289AE;
  margin-bottom: 10px;
  height: 100px;
}
.sidebar {
  position: absolute;
  padding: 10px;
  background-color: #ccc;
  height: 300px;
  width: 100px;
  float: left;
}
.main {
  background-color: #ccc;
  height: 600px;
  margin-left: 110px;
}
.footer {
  background-color: #6289AE;
  margin-top: 10px;
  height: 250px;
}
.top {
  position: absolute;
  top: 10px;
}
.bottom {
  position: absolute;
  bottom: 10px;
}
.clear {
  clear: both;
  float: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://leafo.net/sticky-kit/src/jquery.sticky-kit.js"></script>
<div class="wrapper">
  <div class="header"> <a class="top">header top</a>
    <a class="bottom">header bottom</a>

  </div>
  <div class="content">
    <div class="sidebar"> <a class="top">sidebar top</a>
      <a class="bottom">sidebar bottom</a>

    </div>
    <div class="main"> <a class="top">main top</a>
      <a class="bottom">main bottom</a>

    </div>
    <div class="clear"></div>
  </div>
  <div class="footer"> <a class="top">footer top</a>
    <a class="bottom">footer bottom</a>

  </div>
</div>

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

20
gmo

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

残念ながら、ここに投稿された他の答えは、サイドバーをスムーズにスクロールバックする機能を規定する要件#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。しかし、異なるアプローチを使用するためのロジックは健全です。

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

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

10
Travis Kriplean

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

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もサポートされています。

8
Anoop Naik
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/

1
SezginOnline

WordpressリポジトリWPスティッキーサイドバー。プラグインはまさにあなたが望んだことをします。 、上にスクロールするときにトップ)WP Sticky Sidebar Wordpress repository Link: https://wordpress.org/plugins/mystickysidebar/

1
Manju Talluri

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

ここに私が使用している迅速で汚いサンプル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はスティッキーヘッダーであるため、これを補正する必要があるため、#mastheadの高さを使用しています
  • 私はレスポンシブデザインを使用しており、小さな画面でこれをアクティブにしたくないので、col-2フロートのチェックがあります

誰かがこれをもう少し改良できるなら、それは素晴らしいことです。

0
callmeforsox