first these are my references
jQuery Scroll to bottom of page/iframe
jQuery Scroll To bottom of the page
I create some divs and put them into a div container. I want the container always scrolling down to the newest div at the bottom.
$(document).ready(function() {
var container = $("#container");
var i = 0;
$("#btn").click(function() {
i++;
var div = $("<div></div>");
div.addClass("d");
div.html("Container " + i);
container.append(div);
container.scrollTop(container.height());
});
});
body {
background: white;
}
#container {
height: 160px;
width: 120px;
overflow-y: scroll;
background: gray;
}
.d {
height: 30px;
margin-bottom: 10px;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">-- Add --</button>
<div id="container">
</div>
As you can see, this works fine untill I create more than 8 divs. Then the logic will break and the container does not scroll anymore.
The container should scroll to the current div with the number i (the current index)
Simply because the height is always fixed, instead consider scrolling with the height of all the child elements including their top/bottom margin. In other words, the height of the container if there is no fixed height specified.
To be more precise you only need to scroll with the height of all the child element minus the fixed height of the container which is the overflowing part. That's why your code work partially because until 8 elements you have an overflow lower than the fixed height of the container ( 8 * 40 = 320 => 320 - 160(fixed height) = 160(overflow) )
$(document).ready(function() {
var container = $("#container");
var i = 0;
$("#btn").click(function() {
i++;
var div = $("<div></div>");
div.addClass("d");
div.html("Container " + i);
container.append(div);
container.scrollTop(container.find('.d').length *
($('.d').height() + 10) -
container.height());
});
});
body {
background: white;
}
#container {
height: 160px;
width: 120px;
overflow-y: scroll;
background: gray;
}
.d {
height: 30px;
margin-bottom: 10px;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">-- Add --</button>
<div id="container">
</div>
Related
This question already has answers here:
Detecting when user scrolls to bottom of div with jQuery
(16 answers)
Closed 5 years ago.
I want the alert message to show when the scroll position of the div equals the height of the content inside the div. I have written some jQuery and believe I am very close to being able to do this.
However something is missing. Ignore the scroller div it will be used later. Thanks
$(document).ready(function() {
var box1_height = $("#box1").height();
var scroll_pos = $("#box1").scrollTop();
if (box1_height == scroll_pos) {
alert("It's working");
}
});
* {
margin: 0;
padding: 0;
}
body {
overflow: hidden;
}
#background_1 {
background-image: url("http://placehold.it/350x150");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
position: relative;
}
.scroller {
width: 100%;
height: 100vh;
overflow: scroll;
}
.content {
width: 80%;
height: 80vh;
margin: 10vh auto;
background-color: rgba(0, 0, 0, 0.6);
overflow: scroll;
box-size: border-box;
}
<div id="background_1">
<div class="scroller">
<div id="box1" class="content">
content is here
</div>
</div>
</div>
Here's the CodePen Link.
You need to do the following to detect this:
var container = $("#box1") //Fetch the container element once, so we don't squander performance on re-fetches
var box1_height = container.height(); //Get the visible height of the container (not the actual height with scroll)
var scroll_height = container[0].scrollHeight; //Get the content height of the container
var scroll_pos = container.scrollTop(); //Get the top location of the scrollbar in that container
if(scroll_height == box1_height + scroll_pos){ //Check if we're exactly at the bottom
alert("It's working");
}
Explanation:
This is because you know the top value of the scrollbar, but to detect if you're at the bottom of the container, you actually need to know the bottom value of the scrollbar. That is achieved by:
scroll_height == box1_height + scroll_pos
el.scrollIntoViewIfNeeded() scrolls to el if it's not inside of the visible browser area. In general it works fine but I'm having problems with using it with a fixed header.
I made an example snippet: (The method doesn't work in Firefox, so neither does the demo) https://jsfiddle.net/ahugp8bq/1/
In the beginning all three colored divs are displayed below the fixed header. But if you click "second" and then "first", the beginning of #first will be behind the header, which I don't want.
The problem seems to be that the position of #otherContainer (its padding-top) is pretty much ignored when scrolling up.
Actually, this is quite simple if you use the consistent and supported getBoundingClientRect().top + body.scrollTop way - all you now have to do is reduce the header from it, so just get it and calculate its height.
var header = document.getElementById('container')
var clicks = document.querySelectorAll('#container li');
var content = document.querySelectorAll('#otherContainer > div');
// Turn the clicks HTML NodeList into an array so we can easily foreach
Array.prototype.slice.call(clicks).forEach(function(element, index){
element.addEventListener('click', function(e){
e.preventDefault();
// Set the scroll to the top of the element (top + scroll) minus the headers height
document.body.scrollTop = content[index].getBoundingClientRect().top + document.body.scrollTop - header.clientHeight;
});
});
#container {
position: fixed;
background: yellow;
width: 100%;
height: 50px;
}
ul li {
display: inline;
cursor: pointer;
}
#otherContainer {
padding-top: 60px
}
#first, #second, #third {
height: 500px
}
#first {
background: red
}
#second {
background: green
}
#third {
background: blue
}
<div id="container">
<ul>
<li id="jumpToFirst">first</li>
<li id="jumpToSecond">second</li>
<li id="jumpToThird">third</li>
</ul>
</div>
<div id="otherContainer">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</div>
Content overflows when JavaScript is used to adjust the div height, before it is it used to adjust the div content, if the adjusted div content is higher than the adjusted div height. This does not happen when JavaScript is not used to adjust the div height.
Basically, 2 divs are side by side, and the shorter div is adjusted to the height of the taller div. Then when a button is clicked, content is filled in the original shorter div, but the content overflows, if the content is higher than the adjusted div height. How can we fix this?
<?php
include("ajaxLink.php");
?>
<style>
#wrapper {
border: 1px solid black;
width: 1000px;
}
div:not(#wrapper) {
border: 1px solid red;
display: inline-block;
width: 49%;
}
#content2 {
vertical-align: top;
word-wrap: break-word;
}
</style>
<button onclick = 'fillContent2()'> Click me </button><br><br>
<div id = 'wrapper'>
<div id = 'content1'>
content1content1content1content1content1
content1content1content1content1content1
</div>
<div id = 'content2'>content2</div>
</div>
<script>
$(function(){
var height = getHeight("#content1");
setHeight("#content2", height, "px");
});
function fillContent2() {
$("#content2").html(
"content2content2content2content2content2<br>"+
"content2content2content2content2content2<br>"+
"content2content2content2content2content2"
);
} //end of function fillContent2()
function getHeight(name) {
var height = $(name).height();
return height;
} //end of function getWidth(name)
function setHeight(name,height,type) {
$(name).css("height", height + type);
} //end of function setHeight(name,height,type)
</script>
I've a sticked element which gets the top-alignment from current scroll-offset. Problem is, that the layout is not "retriggerd" if the space from it is free. So there stays a ghost-gap where the sticked element was...
http://fiddle.jshell.net/pPc4V/
The markup is pretty simple:
...
as well as the js:
var $win = $(this);
var sticked = document.querySelector('a.sticked');
$win.on('scroll', function () {
var scrollTop = $win.scrollTop();
sticked.style.top = scrollTop + 'px';
// $win.resize();
});
...and the css looks good so far:
a {
display: inline-block;
width: 90px;
height: 90px;
background: deepskyblue;
}
.sticked {
position: relative;
top: 0;
left: 0;
background: tomato;
}
I tried to trigger the resize-event on scroll (as you see above uncommented), but no success! Any ideas, how to retrigger the layout so that the free-gap is filled with the next floated element?
Update
To clarify what I mean I made a simple image-timelime:
Step 1
Step 2
Step 3
The issue is that you are setting position fixed on an element which is displayed inline. That will cause that space to occur. I have redid your jsFiddle with proper alignment.
To fix it, I added the class "stuck" only when the document's scrollTop position is greater than the scrollTop position of your target element.
jsFiddle: http://fiddle.jshell.net/pPc4V/44/
HMTL:
<div id="grid">
etc...
</div>
CSS:
#grid {
height:1000px;
overflow:hidden;
float:left
}
#grid > a {
display: inline-block;
width: 90px;
height: 90px;
background: deepskyblue;
}
.stuck {
position: fixed;
background: navy !important;
}
JS:
$(window).on('scroll', function () {
var $doc = $(document),
parentElement = $('#grid'),
childToGetStuck = parentElement.find('a:nth-child(5)');
if ($doc.scrollTop() > childToGetStuck.scrollTop()) {
childToGetStuck.addClass('stuck');
//console.log($('.stuck').scrollTop())
} else {
childToGetStuck.removeClass('stuck');
}
});
My HTML basically looks like this:
<div id="#container">
<div id="left_col">
left stuff
</div>
<div id="middle_col">
middle stuff
</div>
<div id="right_col">
<div id="anchor"></div>
<div id="floater>
The problem div
</div>
</div>
</div>
The container div is pushed 82px to the left, because I don't want the rightmost column to be used as part of the centering (there is a header navigation bar above that is the size of left_col and middle_col):
#container {
width: 1124px;
margin-left: auto;
margin-right: auto;
text-align: left;
color: #656f79;
position: relative;
left: 82px;
}
#left_col {
float:left;
width: 410px;
background-color: #fff;
padding-bottom: 10px;
}
#middle_col {
width: 545px;
float: left;
}
#right_col {
float: left;
width: 154px;
margin-left: 5px;
position:relative;
}
#floater {
width: 154px;
}
I'm using the following javascript to keep the #floater div in position as you scroll down the page:
var a = function() {
var b = $(window).scrollTop();
var d = $("#anchor").offset().top;
var c = $("#floater");
if (b > d) {
c.css({position:"fixed",top:"10px"});
} else {
c.css({position:"absolute",top:""});
}
};
$(window).scroll(a);
a();
The problem I'm having is that in WebKit based browsers, once jQuery makes the floater div's positioning fixed so it will stay 10px from the top, that "left: 82px" from #container goes out the window, causing #floater to jump 82px to the left. This doesn't happen in FF or IE. Does anybody know a solution to this?
Update: Solved
I've solved this problem by not using fixed positioning, but instead using absolute positioning. I changed the javascript to set the top CSS property of div#floater to be based on the value $(window).scrollTop() if div#anchor's top offset is greater than $(window).scrollTop(). Pretty simple.
So the a() function now looks like this:
var a = function() {
var b = $(window).scrollTop();
var d = $("#anchor").offset().top;
var c = $("#floater");
if (b > d) {
var t = b-200; //200px is the height of the header, I subtract to make it float near the top
c.css({top:t+"px"});
} else {
c.css({top:""});
}
};