Bootstrap фиксированное положение левого столбца, который становится фиксированным, когда виден нижний колонтитул - PullRequest
1 голос
/ 06 февраля 2020

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

Точное поведение, которое я пытаюсь воспроизвести, можно увидеть здесь: https://store.google.com/gb/collection/accessories_wall ,

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

Я создал JSFiddle, в котором я до сих пор: https://jsfiddle.net/peLwk1cs/2/ и включен сюда для справки, но если кто-то может помочь заставить его работать как пример Google, я был бы очень признателен.

var lastScrollTop = 0;
            $(window).scroll(function() {
                var filterCol = $('.filterContainer');
                var scrollTopPos = $(window).scrollTop();
                
                //Sticky filter col
                if (scrollTopPos > lastScrollTop) {
                    // downscroll code
                    if (scrollTopPos >= 60) {
                        filterCol.addClass("fixed-position");

                        if($(window).scrollTop() >= $('#resultsCol').offset().top + $('#resultsCol').outerHeight() - window.innerHeight) {
                            filterCol.removeClass("fixed-position");
                            filterCol.addClass("absolute-to-bottom");
                        }

                    }
                    else {
                    // upscroll code
                        filterCol.removeClass("absolute-to-bottom");
                        filterCol.removeClass("fixed-position");
                    }
                }
                lastScrollTop = scrollTopPos;    
            }); 
header {
  height: 100px;
  background-color:#0000ff;
}

footer {
  height: 200px;
  background-color:#00ff00;
}

#filtersCol {
  position: relative;
}

.filterContainer {
  background-color:#ddd;
  height: 1200px;
}

.fixed-position {
        position: fixed;
        top: 0;
        overflow: hidden;
        min-height: auto;
        width: 24vw;
        transform: translate3d(0, 0, 0);
        margin-top: 110px;
        height: 1200px;
    }

    .absolute-to-bottom {
        position: absolute;
        bottom: 0;
        width: 24vw;;
    }


#resultsCol {
  height: 3000px;
  background-color:#aaa;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<header>HEADER</header>
<div class="container">
  <div class="row">
    <div id="filtersCol" class="col col-4">
      <div class="filterContainer">
        FILTER COL FOR FIX/ABSOLUTE
      </div>
    </div>
    <div id="resultsCol" class="col col-8">
      RESULTS COL
    </div>
  </div>
</div>
<footer>FOOTER</footer>

Ответы [ 2 ]

0 голосов
/ 07 февраля 2020

Поведение, которое я пытаюсь воспроизвести, можно увидеть в этом примере JSFiddle:

http://jsfiddle.net/bN4qu/5/

Поэтому, когда пользователь прокручивает вниз, левая колонка прилипает, когда достигает дна. Липкий верх удерживает левый столб вверху, а это не то, чего я пытаюсь достичь.

Когда пользователь прокручивает вверх, левый столбик правильно прилипает к верху.

Пример JSFiddle приведен в CoffeeScript, который, к сожалению, не используется в проекте, и мы также используем более новую JQuery.

<div id="header">HEADER</div>
<div id="content">
  <div class="side" id="stick">
    TOP OF LEFT COL
    <div class="bottom">
      BOTTOM OF LEFT COL
    </div>
  </div>
  <div class="main">MAIN CONTENT</div>
</div>
<div id="footer">FOOTER</div>

body {
   margin: 0;
   padding: 10px;
}
#header {
    height: 100px;
    margin: 0 0 10px;
    background: red;
}
#content {
    position: relative;
    float: left;
    width: 100%;
    height: auto;
    margin: 0;
}
.side {
    float: left;
    width: 100px;
    height: 900px;
    margin: 0;
    background: linear-gradient(red, yellow);
}

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

.main {
    height: 2500px;
    margin: 0;
    background: lightgray;
}
#footer {
    clear: both;
    height: 300px;
    background: orange;
}


$.fn.stickyTopBottom = (options = {}) ->
    # only works in browsers that support CSS3 transforms (i.e. IE9+)

    ## ##############
    #initialization
    options = $.extend  
      container: $('body') #reference element for starting and stopping the sticking 
(doesn't actually have to contain the element)
      top_offset: 0 #distance from top of viewport to stick top of element
      bottom_offset: 0 #distance from bottom of viewport to stick bottom of element
    , options

    $el = $(this)

     #Get the top of the reference element. If the container moves, would need to move this into scroll handler. 
    #If the container is translated Y, then this method will fail I believe.
    container_top = options.container.offset().top 
    element_top = $el.offset().top

    viewport_height = $(window).height()
    $(window).on 'resize', -> 
      viewport_height = $(window).height()


     ## #################
    # The meat: scroll handler
    #
    # When moving up or element is shorter than viewport:
    #    if scrolled above top of element, position top of element to top of viewport
    #      (stick to top)
    # When moving down: 
    #    if scrolled past bottom of element, position bottom of element at bottom of viewport
    #      (stick to bottom)

    current_translate = 0
    last_viewport_top = document.documentElement.scrollTop || document.body.scrollTop
    $(window).scroll (event) ->
      viewport_top = document.documentElement.scrollTop || document.body.scrollTop
      viewport_bottom = viewport_top + viewport_height
  effective_viewport_top = viewport_top + options.top_offset
  effective_viewport_bottom = viewport_bottom - options.bottom_offset

  # Need to reset element's height each scroll event because it may have change height 
  # since initialization.
  # Warning: checking height is performance no-no
  element_height = $el.height()

  is_scrolling_up = viewport_top < last_viewport_top
  element_fits_in_viewport = element_height < viewport_height

  new_translation = null
  if is_scrolling_up
    if effective_viewport_top < container_top # if we're scrolled past container top
      new_translation = 0
    else if effective_viewport_top < element_top + current_translate
      new_translation = effective_viewport_top - element_top

  else if element_fits_in_viewport
    if effective_viewport_top > element_top + current_translate
      new_translation = effective_viewport_top - element_top

  else # scrolling down
    container_bottom = container_top + options.container.height() #warning: checking height is performance no-no
    if effective_viewport_bottom > container_bottom #scrolled past container bottom
      new_translation = container_bottom - (element_top + element_height)
    else if effective_viewport_bottom > element_top + element_height + current_translate
      new_translation = effective_viewport_bottom - (element_top + element_height)

  if new_translation != null
    current_translate = new_translation
    $el.css 'transform', "translate(0, #{current_translate}px)" 

  last_viewport_top = viewport_top

 $('#stick').stickyTopBottom
  container: $('#content')
0 голосов
/ 06 февраля 2020

Было бы проще использовать sticky-top, и тогда вам не нужно JS ...

<header>HEADER</header>
<div class="container">
    <div class="row">
        <div id="filtersCol" class="col col-4">
            <div class="filterContainer sticky-top"> FILTER COL </div>
        </div>
        <div id="resultsCol" class="col col-8"> RESULTS COL </div>
    </div>
</div>
<footer>FOOTER</footer>

Демо: https://codeply.com/p/XLuCu9WTo1

Кроме того, если вы хотите, чтобы заголовок был зафиксирован, вы бы добавили следующее, чтобы скорректировать высоту заголовка ...

body {
    padding-top: 100px;
}

.sticky-top {
    top: 100px;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...