Сделать фиксированную прокрутку боковой панели 290px снизу страницы?

Я пытаюсь создать боковую панель, которая работает как на Vice.com. Если вы прокрутите вниз, боковая панель станет фиксированной в определенной точке, а затем, когда боковая панель достигнет определенной точки в нижней части сайта, она продолжит прокрутку вверх с остальной частью сайта.

На моем сайте, я застрял на второй части, которая заставляет боковую панель продолжать прокручивать, как только она попадает в нижнюю часть. 290px снизу, чтобы быть точным.

Вот что я до сих пор:

JavaScript

<script>
jQuery(window).scroll(function () {
    var threshold = 20;
 if (jQuery(window).scrollTop() >= 20)
     jQuery('#sidebar').addClass('fixed');
 else
     jQuery('#sidebar').removeClass('fixed');
});
</script>

CSS

#sidebar {
  margin: 0;
  position: absolute;
  right: 0;
  width: 220px;
}
#sidebar.fixed {
  margin-left: 720px;
  position:fixed;
  right: auto;
  top: 173px;
}

Как сделать фиксированную боковую панель прокруткой вверх, когда она попадает в определенную точку в нижней части?


Изменить # 1

Вот обновленный код Адама. Я использую условный оператор для страниц с другим порогом. Ничего не происходит, когда я использую этот код, то есть боковая панель не добавляет класс fixed и, следовательно, прокручивается нормально, как если бы код там даже не был. Кроме того, я получаю консольную ошибку в этой строке if (scrollTop() >= 236) {, говорящую, что "число не является функцией".

if (jQuery(document.body).hasClass("home")) {

    jQuery(window).scroll(function () {
        var sidebarHeight = jQuery('#sidebar').height(),
            containerHeight = jQuery('#container').height() + 173,
            scrollTop = jQuery(window).scrollTop(),
            clientHeight = scrollTop + jQuery(window).height(),
            threshold = 654;
        if (scrollTop() >= 654) {
            jQuery('#sidebar').addClass('fixed');
        } else if (containerHeight - scrollTop <= sidebarHeight) {
            jQuery('#sidebar').removeClass('fixed').addClass('bottom');
        }
    });

} else if (jQuery(document.body).hasClass("single") || jQuery(document.body).hasClass("page")) {

    jQuery(window).scroll(function () {
        var sidebarHeight = jQuery('#sidebar').height(),
            containerHeight = jQuery('#container').height() + 173,
            scrollTop = jQuery(window).scrollTop(),
            clientHeight = scrollTop + jQuery(window).height(),
            threshold = 20;
        if (scrollTop() >= 20) {
            jQuery('#sidebar').addClass('fixed');
        } else if (containerHeight - scrollTop <= sidebarHeight) {
            jQuery('#sidebar').removeClass('fixed').addClass('bottom');
        }
    });

} else {

    jQuery(window).scroll(function () {
        var sidebarHeight = jQuery('#sidebar').height(),
            containerHeight = jQuery('#container').height() + 173,
            scrollTop = jQuery(window).scrollTop(),
            clientHeight = scrollTop + jQuery(window).height(),
            threshold = 236;
        if (scrollTop() >= 236) {
            jQuery('#sidebar').addClass('fixed');
        } else if (containerHeight - scrollTop <= sidebarHeight) {
            jQuery('#sidebar').removeClass('fixed').addClass('bottom');
        }
    });

}

Ниже представлена ​​структура HTML по запросу:

<!-- BEGIN #masthead-->
<div id="masthead">
    <!-- #secondary-menu -->
    <div id="secondary-menu">

        <!-- .centered-menu -->
        <div class="centered-menu">
            <div class="latest-tweets"></div>
            <div id="search-bar"></div>
            <ul class="social-icons sf-js-enabled"></ul>
        </div>
        <!-- /.centered-menu -->

    </div>
    <!-- /#secondary-menu -->

    <!-- BEGIN #header-->
    <div id="header">

        <!-- #header-inner -->
        <div id="header-inner" class="clearfix">
            <div id="logo"></div>

            <!-- BEGIN #primary-menu -->
            <div id="primary-menu" class="clearfix">

                <!-- .left-menu -->
                <div class="left-menu split-menu"></div>
                <!-- /.left-menu -->

                <!-- .right-menu -->
                <div class="right-menu split-menu">
                    <div class="menu-menu-right-container"></div>
                <!-- /.right-menu -->   

            <!-- END #primary-menu -->
            </div>

        </div>
        <!-- /#header-inner -->

    <!-- END #header -->

    <!-- BEGIN #mobile-menu -->
    <div id="mobile-menu">
        <div id="mobile-inner"></div>
    </div>
    <!-- END #mobile-menu -->

    </div>

    <div id="categories-bar"></div>

</div>
<div id="masthead-space"></div>
<!-- END #masthead -->

<!-- BEGIN #wrapper-->
<div id="wrapper">

    <!-- BEGIN #page-->
    <div id="page">

        <div id="main" class="clearfix">

            <div id="container" class="clearfix">

                <!--BEGIN #content -->
                <div id="content">
                    <div id="sidebar"></div><!-- #sidebar --> 
                </div>

            </div>

        <!--END #main -->
        </div>

    <!--END #page -->
    </div>

<!--END #wrapper -->
</div>

<!--BEGIN #bottom -->
<div id="bottom">

    <!--BEGIN #footer -->
    <div id="footer"></div>

</div>

Ответ 1

Мой совет:

Создайте 2 класса CSS с характеристиками, которые вы хотите, и переключитесь как после достижения точки разрыва, 1 должен быть активным в начале.

FIDDLE

JS

var changePoint = $('#reaching_the_top_of_this_element_activates_change').offset().top;

$(window).scroll(function ()  {
if ($(window).scrollTop() >= changePoint) {
    $('#sidebar').removeClass('blackStatic');
    $('#sidebar').addClass('redFixed');
}
else {
    $('#sidebar').addClass('blackStatic');
    $('#sidebar').removeClass('redFixed');
}

});

CSS

.blackStatic {
    position: static;
    background-color: black;
    color: red;
}
.redFixed {
    position: fixed;
    top: 0;
    background-color: red;
    color: black;
}

Ответ 2

Как я уже сказал в своем комментарии, это может быть отключено, потому что я не вижу структуру html прямо сейчас. Но что-то вроде этого должно работать. Мы получаем высоту scrollbar, container (+ высота заголовка) и высоту области видимости для пользователя или client. Таким образом, используя математику, мы можем сказать, что когда container - scrollTop меньше высоты scrollbar, нам нужна полоса прокрутки, чтобы перестать быть фиксированной. На этом этапе мы удалим фиксированный класс и добавим нижний класс, который имеет только 1 свойство. bottom: 0. Теперь, пока полоса прокрутки находится внутри контейнера, а контейнер имеет position: relative, нижняя часть будет прикреплена к нижней части контейнера.

JavaScript:

jQuery(window).scroll(function(){
    var sidebarHeight = jQuery('#sidebar').height(),
        containerHeight = jQuery('#container').height() + 173,
        scrollTop = jQuery(window).scrollTop(),
        clientHeight = scrollTop + jQuery(window).height(),
        threshold = 20;
    if(scrollTop >= 20){
        jQuery('#sidebar').addClass('fixed');
    }else if(containerHeight - scrollTop <= sidebarHeight){
        jQuery('#sidebar').removeClass('fixed').addClass('bottom');
    }
});

CSS

#sidebar.bottom {
    bottom: 0;
}

Сообщите мне, если это не сработает для вас, и обновите свой вопрос, чтобы иметь html, чтобы это можно было сделать больше для ваших нужд. Кроме того, вам придется иметь дело с прокруткой пользователем страницы, которая не учитывается в настоящее время, но ее было бы сложно добавить.

Ответ 3

взгляните на bootstrap-affix.js http://getbootstrap.com/2.3.2/javascript.html#affix

Он делает именно то, о чем вы просите, и вы можете использовать атрибуты данных html5 для добавления поведения:

<div data-spy="affix" data-offset-top="200">...</div>

Ответ 4

попробуйте этот код (я использовал ID в соответствии с вашей разметкой):

function sidebarScroll()
{
  var tmpWindow = $(window),
      wrapper = $('#wrapper').height(),
      header = $('#header').height(),
      sidebar = $('#sidebar'),
      offsetTop = sidebar.offset().top,
      offsetBottom;

  tmpWindow.scroll(function(){

    offsetBottom = (wrapper + header) - sidebar.height();

    if (tmpWindow.scrollTop() < offsetTop) {
      sidebar.removeClass('fixed bottom');
    } else if (tmpWindow.scrollTop() > offsetBottom) {
      sidebar.removeClass('fixed').addClass('bottom');
    } else {
      sidebar.removeClass('bottom').addClass('fixed');
    }
  });
}

sidebarScroll();

и это классы, которые вам нужны:

#wrapper {
  position: relative;
}
#sidebar {
  width: 220px;
  position: absolute;
  right: 0;
}

#sidebar.fixed {
  position: fixed;
  top: 0;
}

#sidebar.bottom {
  position: absolute;
  bottom: 0;
}

DEMO

Ответ 5

Код, который вы заимствовали у Адама, был скопирован неправильно. Вместо scrollTop вы используете scrollTop(). scrollTop установлен в число, так что, по существу, вы пытаетесь выполнить 20() (или любой номер scrollTop, установленный)

Изменить: чтобы уменьшить избыточность с вашим кодом, я переписал его только для того, чтобы установить порог через тройные выражения if:

jQuery(window).scroll(function () {
    var sidebarHeight = jQuery('#sidebar').height(),
    containerHeight = jQuery('#container').height() + 173,
    scrollTop = jQuery(window).scrollTop(),
    clientHeight = scrollTop + jQuery(window).height(),
    threshold = (jQuery(document.body).hasClass("home"))?654:((jQuery(document.body).hasClass("single") || jQuery(document.body).hasClass("page"))?20:236);
});

Ответ 6

<div class="main">
</div>
<div class="foot">
</div>
<div id="float">
<div class="float_content_head">
I was sending javascript to display
</div><div class="float_content">
d my issue was that I was sending javascript to display console messages. Even when I looked at the file in my browser (not through the application) it showed exactly as I expected it to (eg the extra tags weren't showing), but there were showing in the html/text output and were trying to be parsed. Hope this helps someone!I had a similar problem, and my issue was that I was sending tags we
</div>
</div>

Css
<style type="text/css">
#float{
    background: #fff;
    position:absolute;
    right:30px;
    top:20px;
    width:250px;
    padding:10px;
    border-radius: 6px;
    -webkit-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.43);
-moz-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.43);
box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.43);
}
.float_content_head{
    padding:10px;
    border-bottom: 1px solid #efefef;
    text-align:center;
}
.float_content{
    padding-top:10px;
}
.main{
    width: 800px;
    height: 800px;
    margin: 0 auto;
    border:1px solid #efefef;
    padding: 10px;
    background:#ccc;
}
.foot{
    width: 100%;
    height: 800px;
    margin: 0 auto;
    border:1px solid #efefef;
    padding: 10px;
    background:#096;
}
#box p{
    margin:0;
    padding:0;
}
</style>

JS
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript"> 
$(document).ready(function() {
var starting_position = $('#float').offset();
var top_padding = 50;
var bottom_limit = $('.foot').offset();
var box_height = $('#float').height() + 20;
$(window).scroll(function(){
var top_window = $(window).scrollTop();
if (top_window > starting_position.top && top_window < bottom_limit.top - box_height){
$('#float').stop().animate({top: top_window - starting_position.top + top_padding}, 400);
} else if (top_window > bottom_limit.top - starting_position.top - box_height){
$('#float').stop().animate({top: bottom_limit.top - starting_position.top - box_height }, 400);
} else { $('#float').stop().animate({top: 10 }, 400);           
}
});
});
</script>

Ответ 7

Звучит как это то, что вам нужно (извините мои идентификаторы):

$(document).ready(function() {
// Get the inital position of the menu
    var initialPos = $('#mainnav').offset().top;

//Bind scrolling or resizing
$(window).bind('scroll resize', function() {

// Get the distance from the top of the page to the top of the footer
    var footerTop = $('#footer').length > 0 ? $('#footer').offset().top : $('#footer').offset().top;

// Get the distance from the top of the page to the bottom of the menu
    var navBottom = $(window).scrollTop() + $('#mainnav').height() + 22;

// If the user scrolls further than the height of the header (this method allows for resizing with a max-width layout)
    if ($(window).scrollTop() > initialPos) {
        $('#mainnav').css({
            'position': 'fixed',

           // move the menu based on how far the user has scrolled, and if it exceed the height of the footer
            'top': (footerTop - navBottom > 0 ? 0 : footerTop - navBottom) + 'px',
            'left': ($('#wrapper02').offset().left - $(window).scrollLeft()) + 'px'
        });
    } else {
        $('#mainnav').css({
            'position': 'static'
        });
    }
});
});

Ответ 8

    <style>

     #wrap {
     width:100%;
     height:1000px;
 }  
 #sidebar {
    width:100px;
    height:100px;
    float:left;
    background-color:black;
    color:white;
    vertical-align:middle;
    text-align:center;
 }
    </style>

    <script>
     var offset = $("#sidebar").offset();
 var topPadding = 15;

 $(window).scroll(function () {
    if ($(window).scrollTop() > offset.top) {
        $("#sidebar").stop().animate({
            marginTop: $(window).scrollTop() - offset.top + topPadding
        });
    } else {
        $("#sidebar").stop().animate({
            marginTop: 0
        });
    }
 });

    </script>

    <div id='wrap'>
        <div id="sidebar">Side Bar</div>
    </div>

Ответ 9

Опцией будет waypoints.js, но я думаю, вы можете сделать это с помощью простого jQuery. Путевые точки могут быть для вас, возможно, не... но он может быть использован в этом сценарии. Так что это вариант.

Waypoints.js здесь: http://imakewebthings.com/waypoints/