Reputation: 482
Here is codepen example. Scroll down to tab block. If you scroll top it adds class 'sticked' and if it reaches bottom of parrent element it gets 'sticked2' class. The issue is: when you set top: 0
it works perfect. But when you set the 'sticked' class with top: 1px
or more, it bugges (?) and script stops working. Why is it so?
UPD
Added link to codepen to understand the issue.
var $window = $(window);
$window.scroll(function() {
var labels = $('.forlabels'),
labelsSec = $('.forlabels-section'),
bottomOfLabels = labels.outerHeight() + labels.offset().top,
bottomOfLabelsSec = labelsSec.outerHeight() + labelsSec.offset().top,
topOfLabels = labels.offset().top,
topOfLabelsSec = labelsSec.offset().top,
isAboveTopSec = $window.scrollTop() < topOfLabelsSec,
isAboveTop = $window.scrollTop() < topOfLabels,
isBelowTop = $window.scrollTop() >= topOfLabels,
isBelowBottom = bottomOfLabelsSec <= bottomOfLabels;
if (!isAboveTopSec && ((isBelowTop && !isBelowBottom) || isAboveTop)) {
$('.forlabels')
.addClass('sticked')
.removeClass("sticked2")
.text("Sticked");
} else if (isBelowBottom) {
$('.forlabels')
.addClass('sticked2')
.removeClass('sticked')
.text("Scrolled Below Bottom");
} else {
$('.forlabels')
.removeClass('sticked sticked2')
.text("Not sticked ");
}
});
* {
box-sizing: border-box;
}
.one-half {
position: relative;
padding: 0 10px;
}
.one-half {
-webkit-box-flex: 1;
-ms-flex: 1 45%;
flex: 1 45%;
-webkit-flex: 1 45%;
min-width: 300px;
border: 1px solid red;
height: 100%;
}
.fbox {
height: 1800px;
margin-top: 100px;
border: 1px solid #000;
display: flex;
align-items: flex-start;
}
.forlabels-section {
height: 500px;
background: green;
position: relative;
}
.forlabels {
height: 100px;
background: #777;
}
.forlabels,
.forlabels-section {
width: 200px;
}
.sticked {
position: fixed;
top: 0;
bottom: inherit;
}
.sticked2 {
bottom: 0px;
position: absolute;
top: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="fbox">
<div class="forlabels-section">
<div class="forlabels">Untouched Column</div>
</div>
<div class="one-half columned">
</div>
</div>
Upvotes: 1
Views: 178
Reputation: 8858
The issue is that by adding the top
on the element , you also need to recalculate the value of $(window).scrollTop()
based on the top edge added for comparison between with the other calculated variables.
CSS :
.sticked{
position: fixed;
top: 1px;
bottom: inherit;
}
JS :
var $window = $(window);
$window.scroll(function() {
var windowScrollTop = $window.scrollTop(); // created a variable for $window.scrollTop() value.
if($('.forlabels').hasClass('sticked')) // check if the element has class 'sticked' which adds the top margin of 1px;
windowScrollTop++; // if so, add 1 to $window.scrollTop()
else if($('.forlabels').hasClass('sticked2'))
windowScrollTop--;
var labels = $('.forlabels'),
labelsSec = $('.forlabels-section'),
bottomOfLabels = labels.outerHeight() + labels.offset().top,
bottomOfLabelsSec = labelsSec.outerHeight() + labelsSec.offset().top,
topOfLabels = labels.offset().top,
topOfLabelsSec = labelsSec.offset().top,
isAboveTopSec = windowScrollTop < topOfLabelsSec, // replace reference to $(window).scrollTop() with the variable.
isAboveTop = windowScrollTop < topOfLabels, // replace reference to $(window).scrollTop() with the variable.
isBelowTop = windowScrollTop >= topOfLabels, // replace reference to $(window).scrollTop() with the variable.
isBelowBottom = bottomOfLabelsSec <= bottomOfLabels;
if ( !isAboveTopSec && ((isBelowTop && !isBelowBottom) || isAboveTop)) {
$('.forlabels')
.addClass('sticked')
.removeClass("sticked2")
.text("Sticked");
} else if (isBelowBottom) {
$('.forlabels')
.addClass('sticked2')
.removeClass('sticked')
.text("Scrolled Below Bottom");
} else {
$('.forlabels')
.removeClass('sticked sticked2')
.text("Not sticked ");
}
});
Replace the above js with your js and it would work as expected.
Upvotes: 3