Остановить фиксированное положение в нижнем колонтитуле

Я ищу решение популярной проблемы с остановкой фиксированного объекта в нижнем колонтитуле страницы.

В основном у меня есть фиксированное поле «Поделиться» в левом нижнем углу экрана, и я не хочу, чтобы оно прокручивалось над нижним колонтитулом, поэтому мне нужно, чтобы он остановился примерно на 10px над нижним колонтитулом.

Я рассмотрел другие вопросы здесь, а также другие. Самая близкая/самая простая демонстрация, которую я смог найти, это http://jsfiddle.net/bryanjamesross/VtPcm/, но я не смог заставить его работать с моей ситуацией.

Вот html для окна общего доступа:

    <div id="social-float">
        <div class="sf-twitter">
            ...
        </div>

        <div class="sf-facebook">
            ...
        </div>

        <div class="sf-plusone">
            ...
        </div>
    </div>

... и CSS:

#social-float{
position: fixed;
bottom: 10px;
left: 10px;
width: 55px;
padding: 10px 5px;
text-align: center;
background-color: #fff;
border: 5px solid #ccd0d5;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
display: none;
}

Нижний колонтитул имеет размер #footer и не имеет фиксированной высоты, если это имеет значение.

Если бы кто-то мог помочь мне создать простое решение jQuery для этого, я был бы очень признателен!


person scferg5    schedule 28.12.2011    source источник
comment
Что в Fiddle отличается от того, что вам нужно?   -  person Derk Arts    schedule 28.12.2011
comment
Боковая панель скрипки не фиксируется относительно окна браузера. Я не знаю, может быть, это точно такая же концепция, но я играл с ней и просто не мог заставить ее работать с моим сценарием. Мне нужно, чтобы поле находилось в левом нижнем углу окна, пока оно не достигнет нижнего колонтитула, где оно будет прокручиваться вместе со страницей.   -  person scferg5    schedule 28.12.2011


Ответы (13)


Текущая демонстрация

во-первых, проверяйте его смещение каждый раз, когда вы прокручиваете страницу

$(document).scroll(function() {
    checkOffset();
});

и сделайте его позицию абсолютной, если он был опущен менее чем на 10 пикселей перед нижним колонтитулом.

function checkOffset() {
    if($('#social-float').offset().top + $('#social-float').height() 
                                           >= $('#footer').offset().top - 10)
        $('#social-float').css('position', 'absolute');
    if($(document).scrollTop() + window.innerHeight < $('#footer').offset().top)
        $('#social-float').css('position', 'fixed'); // restore when you scroll up
}

обратите внимание, что родитель #social-float должен быть родственником нижнего колонтитула

<div class="social-float-parent">
    <div id="social-float">
        something...
    </div>
</div>
<div id="footer">
</div>

удачи :)

person Sang    schedule 28.12.2011
comment
Спасибо за ответ. Теперь поле просто мерцает при прокрутке нижнего колонтитула. Есть ли что-то, что мне нужно изменить в CSS? - person scferg5; 28.12.2011
comment
о, извините, это потому, что стиль позиции продолжает переключаться с тех пор, как он был исправлен. попробуйте заменить оператор '›' на '›=' - person Sang; 28.12.2011
comment
Все еще мерцает :( Вот скринкаст того, что происходит, если это поможет: youtu.be/aNnTARjYPOc - person scferg5; 28.12.2011
comment
похоже, что родитель вашего плавающего div содержит нижний колонтитул... я сделал для вас jsfiddle и проверил свой ответ. он хорошо приклеился, но не восстановился, когда я прокрутил вверх. поэтому я добавил код для его решения. это скрипка: jsfiddle.net/Kkv7X, и я снова отредактирую свой ответ :) - person Sang; 28.12.2011
comment
@user984008 user984008, если у вас возникла такая же проблема после того, как вы изменили свой код, как моя скрипка, позвольте мне показать вашу разметку и css. тогда я думаю, что могу исправить ошибку. - person Sang; 28.12.2011
comment
У меня получилось, спасибо! Я очень ценю вашу помощь и быстрые, полезные ответы: D - person scferg5; 28.12.2011
comment
Вы знаете реализацию Bootstrap, кто-нибудь? - person maciek; 29.04.2015

Я только что решил эту проблему на сайте, над которым я работаю, и подумал, что поделюсь ею в надежде, что она кому-то поможет.

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

$(window).scroll(() => { 
  // Distance from top of document to top of footer.
  topOfFooter = $('#footer').position().top;
  // Distance user has scrolled from top, adjusted to take in height of sidebar (570 pixels inc. padding).
  scrollDistanceFromTopOfDoc = $(document).scrollTop() + 570;
  // Difference between the two.
  scrollDistanceFromTopOfFooter = scrollDistanceFromTopOfDoc - topOfFooter;

  // If user has scrolled further than footer,
  // pull sidebar up using a negative margin.
  if (scrollDistanceFromTopOfDoc > topOfFooter) {
    $('#cart').css('margin-top',  0 - scrollDistanceFromTopOfFooter);
  } else  {
    $('#cart').css('margin-top', 0);
  }
});
person user1097431    schedule 16.01.2012
comment
Это сработало блестяще. Главный ответ был отрицательным, потому что мой родитель боковых панелей не был родным братом нижнего колонтитула. Этот ответ менее суетлив в отношении порядка стека div. - person Dan382; 22.08.2016
comment
Блестящий ответ. Это помогло с моей прокруткой, которая перекрывает нижний колонтитул, когда я прокручиваю вниз. Большое спасибо, сэр.. - person Bunny Joel; 20.07.2017
comment
Потрясающий ответ! Очень легко сделать (предыдущее решение JS немного пугает, когда вы мало что знаете ›‹ ). Большое спасибо! - person Claire; 14.08.2020
comment
Работает отлично. - person Polar; 01.09.2020

Вот решение @Sang, но без Jquery.

var socialFloat = document.querySelector('#social-float');
var footer = document.querySelector('#footer');

function checkOffset() {
  function getRectTop(el){
    var rect = el.getBoundingClientRect();
    return rect.top;
  }
  
  if((getRectTop(socialFloat) + document.body.scrollTop) + socialFloat.offsetHeight >= (getRectTop(footer) + document.body.scrollTop) - 10)
    socialFloat.style.position = 'absolute';
  if(document.body.scrollTop + window.innerHeight < (getRectTop(footer) + document.body.scrollTop))
    socialFloat.style.position = 'fixed'; // restore when you scroll up
  
  socialFloat.innerHTML = document.body.scrollTop + window.innerHeight;
}

document.addEventListener("scroll", function(){
  checkOffset();
});
div.social-float-parent { width: 100%; height: 1000px; background: #f8f8f8; position: relative; }
div#social-float { width: 200px; position: fixed; bottom: 10px; background: #777; }
div#footer { width: 100%; height: 200px; background: #eee; }
<div class="social-float-parent">
    <div id="social-float">
        float...
    </div>
</div>
<div id="footer">
</div>

person Lionel Paulus    schedule 07.09.2016

Недавно я столкнулся с этой же проблемой, опубликовав свое решение здесь: using-positionfixed">Предотвращение отображения элемента поверх нижнего колонтитула при использовании position:fixed

Вы можете найти решение, используя свойство position элемента с помощью jQuery, переключаясь между значением по умолчанию (static для divs), fixed и absolute. Вам также понадобится элемент-контейнер для фиксированного элемента. Наконец, чтобы фиксированный элемент не пересекал нижний колонтитул, этот элемент-контейнер не может быть родителем нижнего колонтитула.

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

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

Вот общий пример.

Структура HTML:

<div id="content">
    <div id="leftcolumn">
        <div class="fixed-element">
            This is fixed 
        </div>
    </div>
    <div id="rightcolumn">Main content here</div>
    <div id="footer"> The footer </div>
</div>  

CSS:

#leftcolumn {
    position: relative;
}
.fixed-element {
    width: 180px;
}
.fixed-element.fixed {
    position: fixed;
    top: 20px;
}
.fixed-element.bottom {
    position: absolute;
    bottom: 356px; /* Height of the footer element, plus some extra pixels if needed */
}

JS:

// Position of fixed element from top of the document
var fixedElementOffset = $('.fixed-element').offset().top;
// Position of footer element from top of the document.
// You can add extra distance from the bottom if needed,
// must match with the bottom property in CSS
var footerOffset = $('#footer').offset().top - 36;

var fixedElementHeight = $('.fixed-element').height(); 

// Check every time the user scrolls
$(window).scroll(function (event) {

    // Y position of the vertical scrollbar
    var y = $(this).scrollTop();

    if ( y >= fixedElementOffset && ( y + fixedElementHeight ) < footerOffset ) {
        $('.fixed-element').addClass('fixed');
        $('.fixed-element').removeClass('bottom');          
    }
    else if ( y >= fixedElementOffset && ( y + fixedElementHeight ) >= footerOffset ) {
        $('.fixed-element').removeClass('fixed');           
        $('.fixed-element').addClass('bottom');
    }
    else {
        $('.fixed-element').removeClass('fixed bottom');
    }

 });
person Emanuele Pane    schedule 29.05.2013

Это сработало для меня -

HTML -

<div id="sideNote" class="col-sm-3" style="float:right;">

</div> 
<div class="footer-wrap">
        <div id="footer-div">
        </div>      
</div>

CSS-

#sideNote{right:0; margin-top:10px; position:fixed; bottom:0; margin-bottom:5px;}

#footer-div{margin:0 auto; text-align:center; min-height:300px; margin-top:100px; padding:100px 50px;}

JQuery-

function isVisible(elment) {
    var vpH = $(window).height(), // Viewport Height
        st = $(window).scrollTop(), // Scroll Top
        y = $(elment).offset().top;

    return y <= (vpH + st);
}

function setSideNotePos(){
    $(window).scroll(function() {
        if (isVisible($('.footer-wrap'))) {
            $('#sideNote').css('position','absolute');
            $('#sideNote').css('top',$('.footer-wrap').offset().top - $('#sideNote').outerHeight() - 100);
        } else {
            $('#sideNote').css('position','fixed');
            $('#sideNote').css('top','auto');
        }
    });
}

Теперь вызовите эту функцию следующим образом:

$(document).ready(function() {
    setSideNotePos();
});

PS. Функции Jquery скопированы из ответа на другой аналогичный вопрос в stackoverflow, но у меня он не работал полностью. Поэтому я изменил его на эти функции, как они показаны здесь. Я думаю, что атрибуты позиции и т. д. для ваших div будут зависеть от того, как структурированы div, кто их родители и братья и сестры.

Вышеупомянутая функция работает, когда и sideNote, и footer-wraps являются прямыми братьями и сестрами.

person zookastos    schedule 08.07.2016

Я внес некоторые изменения во второй по популярности ответ, так как обнаружил, что это работает лучше для меня. Изменения используют window.innerHeight, так как это более динамично, чем добавление собственной высоты для навигации (выше использовалось + 570). это позволяет коду динамически работать на мобильных устройствах, планшетах и ​​компьютерах.

$(window).scroll(() => {
            //Distance from top fo document to top of footer
            topOfFooter = $('#footer').position().top;
             // Distance user has scrolled from top + windows inner height
             scrollDistanceFromTopOfDoc = $(document).scrollTop() + window.innerHeight;
             // Difference between the two.
             scrollDistanceFromTopOfFooter = scrollDistanceFromTopOfDoc - topOfFooter; 
            // If user has scrolled further than footer,
              if (scrollDistanceFromTopOfDoc > topOfFooter) {
                // add margin-bottom so button stays above footer.
                $('#floating-button').css('margin-bottom',  0 + scrollDistanceFromTopOfFooter);
              } else  {
                // remove margin-bottom so button goes back to the bottom of the page
                $('#floating-button').css('margin-bottom', 0);
              }
            });
person young sir x    schedule 19.09.2019
comment
Вместо того, чтобы изменять поля, в моем операторе if я использовал JavaScript для изменения положения элемента (вместо фиксированного). ---› document.getElementById('elementId').style.position = absolute; - person Mike Dubs; 11.09.2020
comment
@young sir x Это ИДЕАЛЬНОЕ решение! У меня есть миллион вкладок, открытых в поисках решений, и ваша сработала лучше всего, чтобы моя панель объявлений остановилась над нижним колонтитулом ???? - person brandydoll; 28.12.2020

Теперь это можно сделать с помощью position: sticky.

body,
html {
  height: 100%;
}

body {
  background-color: linen;
  margin: 0;
}


body,
main {
  display: flex;
  flex-direction: column;
}

main,
section {
  flex: 1;
}

main {
  min-height: 200vh;
}

.sticky {
  position: sticky;
  top: 0;
  background-color: lightcoral;
  padding: 1rem;
}

p {
  padding: 0 1rem;
}

footer {
  background-color: lightblue;
  padding: 15rem 1rem;
}
<main>
  <section>
    <div class="sticky">
      <h2>I am sticky<h2>
    </div>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>

  <p>Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. </p>

  <p>Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. </p>

  <p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi. Integer lacinia sollicitudin massa. </p>

  <p>Cras metus. Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante. Nulla quam. Aenean laoreet. Vestibulum nisi lectus, commodo ac, facilisis ac, ultricies eu, pede. Ut orci risus, accumsan porttitor, cursus quis, aliquet eget, justo. Sed pretium blandit orci. Ut eu diam at pede suscipit sodales. Aenean lectus elit, fermentum non, convallis id, sagittis at, neque. Nullam mauris orci, aliquet et, iaculis et, viverra vitae, ligula. </p>
  </section>
  <footer>
    <h2>I am a footer<h2>
  </footer>
</main>

person Ali Klein    schedule 28.04.2021

Я пошел с модификацией ответа @ user1097431:

function menuPosition(){
// distance from top of footer to top of document
var footertotop = ($('.footer').position().top);
// distance user has scrolled from top, adjusted to take in height of bar (42 pixels inc. padding)
var scrolltop = $(document).scrollTop() + window.innerHeight;
// difference between the two
var difference = scrolltop-footertotop;

// if user has scrolled further than footer,
// pull sidebar up using a negative margin
if (scrolltop > footertotop) {
    $('#categories-wrapper').css({
       'bottom' : difference
   });
}else{
    $('#categories-wrapper').css({
       'bottom' : 0
   });
 };
};
person Brainmaniac    schedule 24.10.2017

Теперь вы можете использовать

#myObject{
  position:sticky;
}

Надеюсь это поможет..

person Arthur M    schedule 09.01.2019
comment
Нет поддержки IE 11. - person Josh; 18.11.2019

Я работал над остановкой рекламного баннера в определенном месте перед нижним колонтитулом. И поигрался с кодом, который я нашел выше.

Сработало для меня (баннер исчезает прямо перед нижним колонтитулом и снова появляется при прокрутке вверх):

<style>
#leftsidebanner {width:300px;height:600px;position: fixed; padding: 0;top:288px;right:5%;display: block;background-color: aqua}
</style>

<div id="leftsidebanner">
</div>


<script>

    $.fn.followTo = function (pos) {
    var stickyAd = $(this),
    theWindow = $(window);
    $(window).scroll(function (e) {
      if ($(window).scrollTop() > pos) {
        stickyAd.css({'position': 'absolute','bottom': pos});
      } else {
        stickyAd.css({'position': 'fixed','top': '100'});
      }
    });
  };
  $('#leftsidebanner').followTo(2268);


</script>
person Karina Ro    schedule 24.09.2020

Если ваши элементы глючат, это, вероятно, связано с тем, что когда вы меняете позицию на relative, позиция Y нижнего колонтитула увеличивается, что пытается отправить элемент обратно в fixed, что создает цикл. Этого можно избежать, установив два разных случая при прокрутке вверх и вниз. Вам даже не нужно ссылаться на фиксированный элемент, только на нижний колонтитул и размер окна.

const footer = document.querySelector('footer');
document.addEventListener("scroll", checkScroll);

let prevY = window.scrollY + window.innerHeight;
function checkScroll() {
  let footerTop = getRectTop(footer) + window.scrollY;
  let windowBottomY = window.scrollY + window.innerHeight;
  if (prevY < windowBottomY) {  // Scroll Down
    if (windowBottomY > footerTop)
      setScrolledToFooter(true) // using React state. Change class or change style in JS.
  } else { // Scroll Up
    if (windowBottomY <= footerTop)
      setScrolledToFooter(false)
  }
  prevY = windowBottomY
};

function getRectTop(el) {
  var rect = el.getBoundingClientRect();
  return rect.top;
}

и положение элемента в объекте стиля следующим образом:

position: scrolledToFooter ? 'relative' : 'fixed'
person kuzdogan    schedule 15.12.2020

Чистое CSS-решение

<div id="outer-container">
    <div id="scrollable">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in vulputate turpis. Curabitur a consectetur libero. Nulla ac velit nibh, ac lacinia nulla. In sed urna sit amet mauris vulputate viverra et et eros. Pellentesque laoreet est et neque euismod a bibendum velit laoreet. Nam gravida lectus nec purus porttitor porta. Vivamus tempor tempus auctor. Nam quis porttitor ligula. Vestibulum rutrum fermentum ligula eget luctus. Sed convallis iaculis lorem non adipiscing. Sed in egestas lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc dictum, lacus quis venenatis ultricies, turpis lorem bibendum dui, quis bibendum lacus ante commodo urna. Fusce ut sem mi, nec molestie tortor. Mauris eu leo diam. Nullam adipiscing, tortor eleifend pellentesque gravida, erat tellus vulputate orci, quis accumsan orci ipsum sed justo. Proin massa massa, pellentesque non tristique non, tristique vel dui. Vestibulum at metus at neque malesuada porta et vitae lectus.
    </div>
    <button id="social-float">The button</button>
</div>
<div>
Footer
</div>
</div>

И css здесь

#outer-container {
    position: relative;
}

#scrollable {
    height: 100px;
    overflow-y: auto;
}

#social-float {
    position: absolute;
    bottom: 0px;
}
person Lionel B    schedule 26.03.2019

person    schedule
comment
Код всегда хорош, но он также помогает добавить несколько кратких комментариев/объяснений о том, как это решает исходный вопрос. - person craigcaulfield; 13.10.2018
comment
@Ali Klein вместо установки значения 0, если вы дадите свойство наследования нижнему значению, это будет полезно. то есть const bottomValue = scrollTop › footerToTop ? отличие: наследовать; - person Abhilash Poojary; 04.02.2020