Detect When a Position: Fixed; Element Crosses Over Another Element

Detect when a div with fixed position crosses over another element

You have to take the div heights in account.

There is two "moments" to caculate, the enter and the leave.

So when the bottom of the fixed div enters the top of the scrolled one...

And when the bottom of the scrolled one leaves the top of the fixed.

Here is an example to run:

$(window).scroll(function(){  var fixed = $("div.fixed");    var fixed_position = $("div.fixed").offset().top;  var fixed_height = $("div.fixed").height();
var toCross_position = $(".div-to-cross").offset().top; var toCross_height = $(".div-to-cross").height();
if (fixed_position + fixed_height < toCross_position) { fixed.removeClass('white'); } else if (fixed_position > toCross_position + toCross_height) { fixed.removeClass('white'); } else { fixed.addClass('white'); }
});
.fixed{  position:fixed;  top:calc(50% - 50px);  left:0;  background-color:black;  height:100px;  width:100%;}.white{  background-color:white;}.div-to-cross{  height:100px;  background-color:blue;}
/* just for this demo */.spacer{ height:400px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="fixed"></div><div class="spacer"></div><div class="div-to-cross"></div><div class="spacer"></div>

Detect when a position: fixed; element crosses over another element

$(window).scroll(function () {
if ($(".fixedposition").offset().top < ($(".footer").offset().top - 30)) {
$(".fixedposition").css("top", "30px");
$(".fixedposition").css("display", "block");
} else {
$(".fixedposition").css("display", "none");
}
});

see fiddle here: http://jsfiddle.net/flish/T6x4R/

Of course you should probably do something else other than set display:none; for your fixed div

Detect when multiple static elements overlaps fixed element position on scroll

for (var i = 0; i < images.length; i++) {
var item = images[i]
let b = item.getBoundingClientRect();

if (a.top <= (b.top + b.height) && (a.top + a.height) > b.top) {
logo.style.color = 'white';
break;
} else {
logo.style.color = 'black';
}
};

Updated content:
1. For this solution, I need using break statement in loop, so I am using for instead of foreach
2. We need break if logo is inside in every image.

WHY?:

If logo is inside image1, then its' color can be white, but next step, its' color can be black, because logo is not inside image2.

Below code is more readable for this solution:

const logo = document.querySelector('.logo');
const images = document.querySelectorAll('.image');

function isInsideInImages(images, logoPos) {
for (var i = 0; i < images.length; i++) {
let imagePos = images[i].getBoundingClientRect();

if (logoPos.top <= (imagePos.top + imagePos.height) && (logoPos.top + logoPos.height) > imagePos.top) {
return true;
}
};
return false;
}

window.addEventListener('scroll', function () {

const a = logo.getBoundingClientRect();

if (isInsideInImages(images, a)) {
logo.style.color = 'white';
} else {
logo.style.color = 'black';
}

});

Show/Hide (Toggle) a Fixed Element Depending on Other Elements When Scrolling?

Is this what you want?

If yes, the solution is that you should consider the distance of the window's top to #div2(the center part)

Edited

Add the feature that the comments metioned

$(document).ready(function() {  var $window = $(window);  var div2 = $('#div2');  var div1 = $('#div1');  $window.on('scroll', function() {    var scrollTop = document.documentElement.scrollTop;    var viewport_height = $window.height();    var scrollTop_bottom = scrollTop + viewport_height;    var window_top_to_div2 = ($window.height()-div2.height())/2;            var div1_top = div1.offset().top;    var div1_height = div1.height();    var div1_bottom = div1_top + div1_height;      div2.toggleClass('show', scrollTop >= (div1_top-window_top_to_div2) && (scrollTop + window.innerHeight) <= (div1_bottom+window_top_to_div2));  });});
body {  background: #ccffcc;  padding: 0;  margin: 0;  border: 0;  text-align: center;}
#div1 { background: #0099ff; height: 1500px; color: #fff;}
#div2 { width: 100px; height: 100px; text-align: center; position: fixed; margin: auto; top: 0; left: 0; bottom: 0; right: 0; background: #ffff00; color: #000; display: none;}
#div2.show { display: block;}
#div3 { height: 1500px; color: #000;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<br><br><br><br><br> Scroll area before <b>div1</b> appears<br><br><br><br><br><br><div id="div1"> <div id="div2">This is <b>div2</b></div> This is <b>div1</b> <br> <i>(Toggle show/hide <b>div2</b> when the top of <b>div2</b> passes the top of <b>div1</b>)</i></div><div id="div3"> This is <b>div3</b> <br> <i>(Toggle show/hide <b>div2</b> when the bottom of <b>div2</b> reaches the top of <b>div3</b>)</i></div>

Detect whether an element has position:fixed (possibly by parent element) via jQuery

Here is a solution based on walking through the element's parents, checking the CSS position value for each in turn.

Is this the most efficient way, or is there a way to detect the effective positioning by only examining the element itself?

http://jsfiddle.net/Q4mSJ/

CSS

.trigger-event {background:#ccc}

#one {position:relative; height:50px; width:50px}

#two-wrapper {position:fixed; bottom:0; height:50px; width:50px}
#two {height:50px; width:50px}

HTML

<div id="one" class="trigger-event">element one</div>

<div id="two-wrapper">
<div id="two" class="trigger-event">element two</div>
</div>

JS

function elementOrParentIsFixed(element) {
var $element = $(element);
var $checkElements = $element.add($element.parents());
var isFixed = false;
$checkElements.each(function(){
if ($(this).css("position") === "fixed") {
isFixed = true;
return false;
}
});
return isFixed;
}

$(document).ready(function(){
$('.trigger-event').on('mouseenter', function(event){
var isFixed = elementOrParentIsFixed(event.target);

if (isFixed) {
$(event.target).css('background','red');
} else {
$(event.target).css('background','green');
}
});
});

Is there a way to know when an element pass over another element?

You can listen on an event that fires every time the page is scrolled and then check if it's location is past your hr#line-before-related-article.

Here's an example:

$(window).on('scroll', function() {

if ($(this).scrollTop() + $(this).height() >= $('#line-before-related-article').position().top) {

$('.sticky-footer').hide();

} else if ($('#line-before-related-article').position().top >= $(this).scrollTop()) {

$('.sticky-footer').show();
}
})

If you want something that's a little more performant, you can use something called a debounce function...

For those of you who don't know what a debounce function does, it limits the rate at which a function can fire. A quick example: you have a resize listener on the window which does some element dimension calculations and (possibly) repositions a few elements. That isn't a heavy task in itself but being repeatedly fired after numerous resizes will really slow your site down. Why not limit the rate at which the function can fire?

More on that here: https://davidwalsh.name/javascript-debounce-function

Fixed position but relative to container

Short answer: no. (It is now possible with CSS transform. See the edit below)

Long answer: The problem with using "fixed" positioning is that it takes the element out of flow. thus it can't be re-positioned relative to its parent because it's as if it didn't have one. If, however, the container is of a fixed, known width, you can use something like:

#fixedContainer {
position: fixed;
width: 600px;
height: 200px;
left: 50%;
top: 0%;
margin-left: -300px; /*half the width*/
}

http://jsfiddle.net/HFjU6/1/

Edit (03/2015):

This is outdated information. It is now possible to center content of an dynamic size (horizontally and vertically) with the help of the magic of CSS3 transform. The same principle applies, but instead of using margin to offset your container, you can use translateX(-50%). This doesn't work with the above margin trick because you don't know how much to offset it unless the width is fixed and you can't use relative values (like 50%) because it will be relative to the parent and not the element it's applied to. transform behaves differently. Its values are relative to the element they are applied to. Thus, 50% for transform means half the width of the element, while 50% for margin is half of the parent's width. This is an IE9+ solution

Using similar code to the above example, I recreated the same scenario using completely dynamic width and height:

.fixedContainer {
background-color:#ddd;
position: fixed;
padding: 2em;
left: 50%;
top: 0%;
transform: translateX(-50%);
}

If you want it to be centered, you can do that too:

.fixedContainer {
background-color:#ddd;
position: fixed;
padding: 2em;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}

Demos:

jsFiddle: Centered horizontally only

jsFiddle: Centered both horizontally and vertically

Original credit goes to user aaronk6 for pointing it out to me in this answer



Related Topics



Leave a reply



Submit