Reputation: 642
I have a div
with position: absolute
and overflow: auto
. Inside this div
I have a div
that should act sticky and should be fixed(top: 0, bottom: 0, overflow: auto
) when I scroll.
I can fix this div
, but I can't return it to original position because I can't attached the scroll event when this div
is fixed.
$('.right').scroll(function() {
if ($('.scroll').offset().top <= 0) {
$('.scroll').css({
'position': 'fixed',
'top': 0,
'left': '20px',
'right': '0',
'overflow': 'auto'
})
}
})
Please check my JSFiddle for more info - JSFIDDLE
Thank you.
Upvotes: 14
Views: 14523
Reputation: 1531
You can try the following example:
Firstly, instead of adding the css as inline styles, create a css class that you can add and remove from the .scroll
element.
CSS
.fixed-top {
position:fixed;
top:0;
left:20px;
right:20px;
}
Wrap your .scroll element with another div which will be used in the javascript to keep track of the original height of your .scroll
div.
HTML
<div class="scroll-wrapper">
<div class="scroll"></div>
</div>
Lastly, store the scrollTop value in a variable when the fixed position is applied for the first time. You can then use that value to determine when to remove the fixed styles from the .scroll
div. Also set the height of the .scroll-wrapper
element equal to the height of your .scroll
element to make sure the content is scrollable.
Javascript
var startScrollTop = 0;
$('.right').scroll(function () {
var $scroll = $('.scroll');
if ($scroll.offset().top <= 0 && $('.right').scrollTop() > startScrollTop) {
if (startScrollTop === 0) {
startScrollTop = $('.right').scrollTop();
}
$('.scroll-wrapper').css("height", $('.scroll').height() + 300);
$scroll.addClass("fixed-top");
} else {
$scroll.removeClass("fixed-top");
}
})
Take a look at this fiddle. http://jsfiddle.net/a924dcge/25/
Hope that helps!
Upvotes: 0
Reputation: 546
It is very strange task you want to accomplish :)
But anyway there is the problem:
When you set you inner div
to position: fixed
you positioned this div
above your div.right
and it is prevents scrolling event from fire.
So what you need is to set pointer-events: none
to the div.scroll
to allow your div.right
listen scroll events without any problems.
But when you do that you will face another problem - when you set your div.scroll
to position: fixed
it will lose its place inside the div.right
and div.right
jumps to the top of the scroll automatically. To prevent that you need to create clone of the div.scroll
and set his height
to 0
initially, and to auto
when your inner element is fixed.
Note pointer-events: none
- disable all mouse events including the text selection.
There is the code:
JS
$(document).ready(function() {
var cnt = $('.right');
var scrollEl = $('.scroll');
var scrollClone = scrollEl.clone().addClass('clone');
scrollEl.before(scrollClone);
cnt.scroll(function() {
var expression = scrollClone.offset().top <= 0;
scrollEl.toggleClass('stick', expression);
scrollClone.toggleClass('stick-clone', expression);
})
})
CSS
.scroll {
background: yellow;
pointer-events: none;
overflow: hidden; /* Remove top offset from h1*/
}
.scroll.stick {
position: fixed;
left: 20px;
right: 0;
top: 0;
}
.scroll.clone {
height: 0;
overflow: hidden;
}
.scroll.clone.stick-clone {
height: auto;
}
Upvotes: 1
Reputation: 1131
Set the outside div to
position: relative;
Set the inside div to
position: absolute;
top: 15px;
right: 15px;
This will put the top right corner of the inside div at the designated location within the parent container. When setting position absolute, the image is set relative to the first parent container with position defined to anything other than default, I believe. If there is no DOM element assigned a position, the absolute element will be positioned relative to the viewport.
Upvotes: 1
Reputation:
Here's how I would do it. This doesn't position it fixed but it has the same appearance. Once scrollTop is equal to or greater than where the top of the fixed content "should be" then we set the top absolutely to that of scrollTop, if you scroll upwards once the scrollTop reaches the point where the fixed content used to be, it will drop it again.
$(document).ready(function() {
oldOffset = $('.scroll').offset().top;
$('.right').scroll(function() {
if ($('.right').scrollTop() > oldOffset) {
$('.scroll').css({
'position': 'absolute',
'top': $('.right').scrollTop(),
'left': '20px',
'right': '0',
'overflow': 'auto'
});
}
});
});
(Demo)
Upvotes: 8