#javascript #html #jquery #css #scroll
Вопрос:
Я создал липкую боковую панель для своего блога, но теперь мне нужен липкий элемент, чтобы остановить прокрутку, когда я дойду до нижнего колонтитула. Причина в том, что боковая панель перекрывает элементы нижнего колонтитула. Как я могу решить эту проблему?
Рабочая возня с перекрывающейся проблемой:
https://jsfiddle.net/j7x5hLy3/
Это ИМЕННО то, чего я пытаюсь достичь:
https://abouolia.github.io/sticky-sidebar/examples/basic.html
Посмотрите, что происходит, когда боковая панель достигает дна. Я НЕ ПЫТАЮСЬ ИСПОЛЬЗОВАТЬ Z-ИНДЕКС. Я говорю это потому, что в некоторых других вопросах люди публикуют «решения», в которых используется z-индекс. Я не пытаюсь ничего скрыть, я пытаюсь заставить его перестать прокручиваться, когда он достигнет нижнего колонтитула.
jQuery(document).ready(function($) {
function isScrolledTo(elem) {
var docViewTop = $(window).scrollTop(); //num of pixels hidden above current screen
var docViewBottom = docViewTop $(window).height();
var elemTop = $(elem).offset().top; //num of pixels above the elem
var elemBottom = elemTop $(elem).height();
return ((elemTop <= docViewTop));
}
var catcher = $('#bannernormal');
var sticky = $('#bannerfixo');
if ($(window).width() >= 100) {
$(window).scroll(function() {
if (isScrolledTo(sticky)) {
sticky.css('position', 'fixed');
sticky.css('top', '0px');
}
var stopHeight = catcher.offset().top catcher.height();
if (stopHeight > sticky.offset().top) {
sticky.css('position', 'absolute');
sticky.css('top', stopHeight);
}
});
} else {
$(window).unbind('scroll');
}
});
#bannernormal {
margin: auto;
display: table;
width: 200px;
height: 400px;
border: 1px solid #000;
margin: 5px;
}
#bannerfixo {
margin: 5px;
width: 200px;
height: 400px;
border: 1px solid #000;
margin: 5px;
}
#sidebar {
float: left;
}
#content {
float: right;
}
#footer {
display: block;
clear: both;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<div id="content">
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
Content <br><br><br><br><br><br><br><br>
</div>
<div id="sidebar">
<div id="bannernormal">
This is the "catcher" <code>div</code>
</div>
<div id="bannerfixo" style="position: absolute; top: 413px;">
This is the "sticky" <code>div</code>
</div>
</div>
<div id="footer">Everything should stop before this part.
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
1010101010101011010<br/>
</div>
Ответ №1:
Чтобы все было просто, вот три вложенных дива. Корневой div представляет корень вашего документа (обычно <body
) Содержимое может быть любым div, если оно имеет position: relative
У div <div id="relativeTop">
должно было быть position: absolute
. relativeTop
теперь он будет располагаться внутри родительского элемента, но вы можете расположить его явно, используя верхний, правый, нижний и левый. Если родитель не relative
является таковым , его дети смогут свободно покинуть его границы и вместо этого расположат своих детей относительно окна.
В javascript я слушаю событие прокрутки
document.addEventListener('scroll', (e) => {
Это означает, что вы можете установить верхнее или нижнее значение.
Посмотри на чек:
if (window.scrollY rect.height > parentRect.height) {
Если это верно, вы будете знать, что div будет находиться вне родительского объекта, и вы можете настроить top: 0px
его так, чтобы он был привязан к основанию своего родителя.
В противном случае верхнее значение устанавливается в положение прокрутки документа:
el.style.top = window.scrollY "px";
document.addEventListener('scroll', (e) => {
const el = document.getElementById("relativeTop");
const parent = el.parentNode;
const parentRect = parent.getBoundingClientRect();
const rect = el.getBoundingClientRect();
if (window.scrollY rect.height > parentRect.height) {
el.style.bottom = "0px";
} else {
el.style.top = window.scrollY "px";
}
});
#body {
border: 1px dotted yellow;
height: 1500px;
}
#content {
position: relative;
border: 1px dotted red;
height: 1000px;
margin: 10px;
width: 2000px;
}
#relativeTop {
border: 1px dotted blue;
position: absolute;
left: 0;
width: 200px;
height: 100px;
}
<div id="body">
<div id="content">
<div id="relativeTop">
</div>
</div>
</div>
Комментарии:
1. Когда я пытаюсь использовать ваш код, консоль выдает ошибку «document.addEventListener».
Uncaught TypeError: Cannot read properties of null (reading 'parentNode') at HTMLDocument.<anonymous>
2. У вас есть этот раздел на вашей странице:
<div id="relativeTop">
?document.getElementById("relativeTop");
возвращает null, если он не может найти элемент, поэтомуconst el
имеет значение null и null.parentNode не существует 🙂3. Я должен задаться вопросом, однако, ответ K_Hs идеален, и вы должны быть в состоянии заставить его работать во многих сценариях, если вы готовы работать с flexbox:
display: flex
4. «document.addEventListener(‘прокрутка’, (e) => {» также возвращает синтаксическую ошибку в редакторе.
5. Я использовал «document.addEventListener(‘прокрутка’, функция(e) {» вместо этого, это правильно?
Ответ №2:
.container {
display: flex;
margin-bottom: 10px;
}
.section {
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
.sidebar {
width: 180px;
height: 160px;
background: green;
margin-right: 10px;
}
.normal {
background: yellow;
margin-bottom: 10px;
}
.sticky {
background: red;
position: sticky;
top: 0;
}
.content {
width: 100%;
background: lightgray;
}
.footer {
background: pink;
height: 800px;
}
<div>
<div class="container">
<div>
<div class="sidebar normal section">
Normal
</div>
<div class="sidebar sticky section">
Sticky
</div>
</div>
<div class="content">
Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
<br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
</div>
</div>
<div class="footer section">
Footer
</div>
</div>
Комментарии:
1. Хорошее решение, но вы, возможно, захотите добавить некоторые объяснения относительно того, почему эта оценка работает так, как она работает.
2. Это не сработает так, как должно. CSS не в состоянии достичь того, что мне нужно.