Scroll div depending on parent position - javascript

I have a parent div with two child divs. The first child should be fixed when the parent is in viewport. The second child should scroll into position and overlap the first. Both child divs should be removed and follow the parent as soon as they reach the bottom of the parent.
Right now, I'm adding a class on scroll position but I'm not sure how to detect when the child is at bottom of parent and then remove the class.
var sticky = $('.sticky'),
scroll = $(window).scrollTop();
if (scroll >= 70) {
sticky.addClass('fixed');
} else {
sticky.removeClass('fixed');
}
How can I make the child divs follow the parent in the best way? I've tried to search for something similar what I want but couldn't find any good explanation.
This fiddle is what I've got so far.

If I am understanding this correctly, what you could do is measure bottom of parent div and child sticky div relative to the document.body, and if child element's bottom crossing parent's bottom you can remove .fixed class.
Something like this.
$(window).scroll(function(){
var sticky = $('.sticky'),
scroll = $(window).scrollTop();
if (scroll >= 70) {
sticky.addClass('fixed')
}else {
sticky.removeClass('fixed');
}
if(getBottom('.sticky') >= getBottom('.holder')){
sticky.removeClass('fixed');
}
});
function getBottom(element){
var $elm = $(element);
var offset = $elm.offset();
var top = offset.top;
return top + $elm.outerHeight();
}
body { margin: 0; }
section {
height: 2000px;
padding-top: 100px;
}
div {
width: 300px;
height: 100px;
}
.holder {
border: 1px solid black;
width: 500px;
height: 200px;
position: relative;
}
.sticky {
top:30px;
left:10px;
background: orange;
z-index: 9999;
position: relative;
}
.other-div {
background: gold;
top: 20px;
z-index: 0;
}
.fixed {
position: fixed;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Divs</title>
</head>
<body>
<section>
<div class="holder">
<div class="other-div fixed">This div should stay fixed for a while</div>
<div class="sticky">This div will become fixed on scroll</div>
</div>
</section>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</body>
</html>
Jsfiddle of the above snippet https://jsfiddle.net/azs06/3ubshm4t/7/
Note, I made some css changes, which you can adjust as you need.

Related

How can I revert the width of a div after animation?

Here's what I'm trying to do:
A position:sticky div has a rectangle in it (id=mysquare). After scrolling a bit, the width of mysquare should shrink using jquery's animate. Then, when scrolling back up, mysquare should instantly grow back to its original width.
The problem:
The animation bit works fine. What doesn't work is reverting back to mysquare's original width. When you scroll back up after mysquare shrinks to 100px, it stays the same (when it should theoretically go back to 150px).
var headheight = $(".myheading").height();
$(function() {
$(window).scroll(function() {
if ($(this).scrollTop() > headheight) {
//if scrolled past myheading
//Gradually change the width of the square to 100px, from 150px
$("#mysquare").animate({
width: "100px",
}, 1500);
}
if ($(this).scrollTop() < headheight) {
//If not scrolled past myheading
//Keep the square big
$("#mysquare").width("150px");
}
})
});
div.sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
background-color: yellow;
padding: 10px;
font-size: 20px;
}
#mysquare {
height: 50px;
background-color: #555;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div class="myheading" style="height: 50px;"></div>
<div class="sticky">Hello
<div id="mysquare" style="width 150px;">
</div>
</div>
<main style="height:500px;"></main>
</body>
</html>
A JSFiddle: https://jsfiddle.net/82n16x07/7/
On a side note, mysquare seems to take up the entire width of the screen when first loaded in. Any help with that would also be appreciated.
after animation you need to remove the element and replace it to have other css applied
var headheight = $(".myheading").height();
$(function() {
$(window).scroll(function() {
if ($(this).scrollTop() > headheight) {
//if scrolled past myheading
//Gradually change the width of the square to 100px, from 150px
$("#mysquare").animate({
width: "100px",
}, 1500);
}
if ($(this).scrollTop() < headheight) {
var elm = document.getElementById('mysquare');
var newone = elm.cloneNode(true);
elm.parentNode.replaceChild(newone, elm);
//If not scrolled past myheading
//Keep the square big
$("#mysquare").width("500px");
}
})
});
div.sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
background-color: yellow;
padding: 10px;
font-size: 20px;
}
#mysquare {
height: 50px;
background-color: #555;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div class="myheading" style="height: 50px;"></div>
<div class="sticky">Hello
<div id="mysquare" style="width 150px;">
</div>
</div>
<main style="height:500px;"></main>
</body>
</html>
Your initial width problem is caused by an incorrect style directive, with a missing colon:
<div id="mysquare" style="width 150px;">
should be:
<div id="mysquare" style="width: 150px;">
The main problem is caused by the fact that the animate() function is repeatedly called when the scroll condition is true, and these function calls stack up. If you wait long enough, they clear, and the box is returned to it's normal size.
To fix this, you can add a shrunk flag to determine if the box is shrunk or not, and check this flag to determine whether or not to issue a new animate() call.
var headheight = $(".myheading").height();
var shrunk=false;
$(function() {
$(window).scroll(function() {
if ($(this).scrollTop() > headheight && !shrunk) {
//if scrolled past myheading
//Gradually change the width of the square back to the size of the new image
shrunk=true;
$("#mysquare").animate({
width: "100px",
}, 1500);
}
if ($(this).scrollTop() < headheight) {
//If not scrolled past myheading
//Keep the square big
shrunk=false;
$("#mysquare").width("150px");
}
})
});
div.sticky {
position: -webkit-sticky;
position: sticky;
top: 0;
background-color: yellow;
padding: 10px;
font-size: 20px;
}
#mysquare {
height: 50px;
width:150px;
background-color: #555;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div class="myheading" style="height: 50px;"></div>
<div class="sticky">Hello
<div id="mysquare" style="width: 150px;">
</div>
</div>
<main style="height:500px;"></main>
</body>
</html>
Just try with this. hope this works for you.
var lastScrollTop = 0;
$(window).scroll(function(event){
var thisScrolltop = $(this).scrollTop();
if (thisScrolltop > lastScrollTop){
// write code here, when down scroll
} else {
// write code here, when up scroll
}
lastScrollTop = thisScrolltop;
});

Fix an element when it reaches the top of the screen using javascript and css

I have an element, that I wish to stick on top after it reaches the top of the screen.
<div id="HeaderWrapper">
...
<div id="Navigation">
Navigation
</div>
...
</div>
I am adding an event listener on scroll, which would call a function to check the posting of the element by using getBoundingClientRect() method. If the top or the y of the element is less then 0 relative to the viewport, then I would like to fix/stick the header. Again if its more than 0 then I would like to remove the fix position. In both the cases, I am adding and removing a class name of fixed_navbar which has the property of fix position.
document.addEventListener("scroll", function() {
const el = document.getElementById("Navigation");
let rect = el.getBoundingClientRect();
if (rect.top <= 0) {
el.classList.add("fixed_navbar");
} else {
el.classList.remove("fixed_navbar");
}
});
You can also the check the codepen demo.
When the position top of the element is more than zero it works fine. Also when scrolling down to the position where the element's top position is less than 0 it sticks to the page and has the fixed propery. But again when scrolling back to the position when the element's top is more than 0, the element still has the fixed propery and stick's to the top of the screen. How can I make the element stick to the top when it reaches the top of the screen and again when the element is below the top of the screen remove the fixed postion?
You can achieve this with CSS alone, by using:
position: sticky
When declaring position: sticky; you will also need to declare a top style (eg. top: 0;) to indicate at which point you want the element to become "stuck".
Working Example:
header {
height: 600px;
}
.navigation {
position: sticky;
top: 0;
margin-top: 150px;
}
<header>
<div class="navigation">Navigation</div>
</header>
Further Information:
position: sticky works in the following browsers:
https://caniuse.com/#feat=css-sticky
Try This
if (rect.top <= 0) {
In if condition you write rect.top < 0 that is wrong for your requirement
#Rounin provide an awesome solution. Although I fix your issue in JavaScript. you can check this
document.addEventListener("scroll", function() {
const el = document.getElementById("Navigation");
let rect = el.getBoundingClientRect();
if (rect.top <= 0) {
el.classList.add("fixed_navbar");
} else {
window.onscroll = function() {myFunction()};
function myFunction() {
if ( document.body.scrollTop < 100 ) {
el.classList.remove("fixed_navbar");
}
}
}
});
* {
margin: 0;
padding: 0;
}
#HeaderWrapper {
background: lightgrey;
height: 1500px;
}
.box {
background: skyblue;
width: 100%;
height: 100px;
}
#Navigation {
background: green;
}
.fixed_navbar {
position: fixed;
z-index: 1000;
width: 100%;
left: 0;
top: 0;
}
<div id="HeaderWrapper">
<div class="box"></div>
<div id="Navigation">
Navigation
</div>
</div>

Make window scroll function operate only in one div

On a webpage I have multiple sections. In one of this sections I show lots of content blocks. These blocks can be filtered via a panel that floats on the right side.
Currently this floating panel is visible on all the sections of the webpage but I want it to only be visible within the section that I assign it to.
Ideally I would want it to have it stuck in the top right corner of the section on page load. Then when the user gets to the section it needs to keep scrolling with the user until it reaches the end then it needs to stay there.
When the user is finished on the page and scrolls back upwards it needs to do the same as above only in reverse order.
What needs to be done
Make it only visible within the section (assigning a specific section)
Make it stuck in the top right corner on page load
Disallow continuing to the next section after reaching the end of the assigned section.
jsFiddle
https://jsfiddle.net/nfuL86hg/
HTML:
<div id="section-aaa"></div>
<div id="section-bbb">
<div id="content"></div>
<div id="scroller">
Hello<br>
World<br>
</div>
</div>
<div id="section-aaa"></div>
JS:
(function ($) {
$(document).ready(function() {
$(window).scroll(function(){
$("#scroller").stop().animate({"marginTop": ($(window).scrollTop()) + "px", "marginLeft":($(window).scrollLeft()) + "px"}, "slow" );
});
});
})(jQuery);
CSS:
#section-aaa{
position:relative;
height:500px;
background:red;
}
#section-bbb {
position:relative;
height:1000px;
background:grey;
}
#content {
height:100%;
}
#scroller {
background-color: #fca9a9;
width: 250px;
position: absolute;
top: 50px;
right: 0;
z-index: 1;
}
Thanks everyone for helping.
PS: If you know a better title please post it in the comment area. At the moment I could not think of a better one.
here is one demo
https://jsfiddle.net/nfuL86hg/2/
(function ($) {
$(document).ready(function() {
$(window).scroll(function(e){
if(getIsInArea()){
console.log('animate');
$("#scroller").stop().animate({
"marginTop": ($(window).scrollTop()) + "px",
"marginLeft":($(window).scrollLeft()) + "px"
}, 100 );
}
});
function getIsInArea(){
var w = $(window).scrollTop();
var p = $('#section-bbb').position();
var top = p.top;
var down = top+$('#section-bbb').innerHeight();
if(w>=top && w<=down) {
return true
}
return false;
}
});
})(jQuery);
Expect goes near you need it
Another solution wihtout the animation, in case you want it simpler.
Check it on this JSFiddle.
HTML
<div id="section-aaa"></div>
<div id="section-bbb">
<div id="content"></div>
<div id="scroller">
Hello<br>
World<br>
</div>
</div>
<div id="section-aaa"></div>
CSS
body {
padding: 0;
margin: 0;
}
#section-aaa{
position:relative;
height:500px;
background:red;
}
#section-bbb {
position:relative;
height:1000px;
background:grey;
}
#content {
height:100%;
}
#scroller {
background-color: #fca9a9;
width: 250px;
position: absolute;
top: 50px;
right: 0;
z-index: 1;
}
JavaScript
(function ($) {
$(document).ready(function() {
$(window).scroll(function(){
if ($(window).scrollTop() > $('#section-bbb').offset().top) {
if ($(window).scrollTop() < $('#section-bbb').offset().top + $('#section-bbb').height() - 100 - $('#scroller').height() ){
$('#scroller').css({"position":"fixed", "top":"50px", "bottom":"auto"});
} else {
$('#scroller').css({"position":"absolute", "top":"auto", "bottom":"50px"});
}
} else {
$('#scroller').css({"position":"absolute", "top":"50px", "bottom":""});
}
});
});
})(jQuery);
In Javascript it checks if the scroll top of the window is in the section-bbb div and if it is, it changes the css of the scroller div to have position: fixed. If the scroll top of the window is below the section-bbb div, it changes back the css of the scroller div to have position: absolute and be on the bottom of the section-bbb div (top:auto, bottom:50px). If the scroll top of the window is above the section-bbb div, it changes the css of the scroller div to have position: absolute and be on the top of the section-bbb div (top:50px, bottom:auto).

div percentage height does not work as intended - inside fixed div

issue:
http://jsfiddle.net/um2b98we/5/
I have a small problem. I try to create a navigation where the child (blue box) div is 75% screen height. I have no problems at all, as long as the parent (green box) is in relative position.
However, when I scroll down, I want the parent to be fixed on top of the screen. However then the child changes the height to 75% of the parent but I need it to keep being 75% height of the screen
for sample code, go to the link above:
#scroll, #header, #one, #two {width: 100%}
#scroll {height: 2000px;}
#one {
background: red;
height:50px;
}
#two {
background: green;
height:50px;
}
#two.fixed{
position:fixed;
top:0;
}
#sub {
position: absolute;
height: 75%;
width: 80%;
background: blue;
margin-top:50px;
}
<div id="scroll">
<div id="header">
<div id="one"></div>
<div id="two">
<div id="sub"></div>
</div>
</div>
</div>
I have been trying to fix it for a long time without any success. I would appreciate the help.
You could give the div height with javascript:
$(window).bind('scroll', function(){
var windowHeight = $(window).height();
$('#two').toggleClass('fixed',$(window).scrollTop() > 50);
$('#sub').css('height',windowHeight *.75);
});
or add it after you applied the fixed class to it:
$(window).scroll(function() {
var scroll = $(window).scrollTop(),
windowHeight = $(window).height();
if (scroll >= 50) {
$("#two").addClass("fixed");
$('#sub').css('height', windowHeight *.75);
} else {
$("#two").removeClass("fixed");
}
});

How to access position of an element relative to its parent element

I want to get the position of an element relative to its parent element. So for this i am using jquery position function I created a JsFiddle.
In this fiddle i am accessing the top & left position of #child element. It should return top : 0 and left : 0 because it is the children of #p element and its position is relative but it is returning top : 223px and left : 1px. Can anyone please help me ?
here is the tweak
The problem was you did not specify the parent's position as relative. So the child position was calculated with respect to body
<style type="text/css">
#gp {
width: 500px;
height: 200px;
margin: 0;
border: 1px solid black;
background-color:gray;
overflow:hidden;
}
#p {
width: 600px;
height: auto;
float: left;
position: relative;
}
#child{
position: relative;
}
</style>
<div id="gp">
<div id="p">
<div id="child">
</div>
</div>
</div>
jQuery(document).ready(function(){
alert($("#child").position().top + " " + $("#child").position().left);
});
Perhaps something like this :
function relative_pos(node) {
var parentOf = $(node).parent().offset();
var child = $(node).offset();
return {top: child.top - parentOf.top, left: child.left - parentOf.left};
}
console.log(relative_pos("#child"));
Try !!!

Categories

Resources