I'm working on a project that animate on page scroll.
This is the element I want to animate.
<h1 style="position: relative; top: 0; left: 0;"
onscroll="animateAfterPosition(200)"
data-animate-left="50px" data-animate-top="50px"
data-animate-time="0.2s">Animation on scroll</h1>
This is my JavaScript
function animateAfterPosition(scroll) {
console.log(scroll);
function(){
if (window.scrollY <= scroll) {
this.classList.add('animateAfterPosition');
} else {
this.classList.remove('animateAfterPosition');
}}
And this is my CSS
.animateAfterPosition {
transition: attr(data-animate-time);
left: attr(data-animate-left);
top: attr(data-animate-top);}
I need to run the function animateAfterPosition from the html. I expected to run the function with onscroll event, but it doesn't work. So how can I do this?
Edit
I found that css attr() is only working with the content: property and I managed to do it with JavaScript
You need to add selector to toggle class the animation. And your current css doesn't have enough height to make scrolling window. Here's an simple snippet to run your function onload, update onscroll and toggling class.
var dataAnimate = document.querySelector('[data-animate]');
function animateAfterPosition(scroll) {
dataAnimate.classList.toggle('active', window.scrollY <= scroll);
}
window.addEventListener("scroll", function() {
return animateAfterPosition(200);
});
.animateAfterPosition {
transition: attr(data-animate-time);
left: attr(data-animate-left);
top: attr(data-animate-top);
}
[data-animate] {
height: 1000px;
}
<body onload="animateAfterPosition(200)">
<h1 style="position: relative; top: 0; left: 0;"data-animate-left="50px" data-animate-top="50px" data-animate-time="0.2s" data-animate>Animation on scroll</h1>
</body>
Fiddle: https://jsfiddle.net/rafonzoo/phmg0u46/
A minimalistic solution
You can configure it using the first 4 variables in the function. I recommend adding the indicator class to the body itself and then use a selector like body.beyond-that-point h1. This way, it's possible to make several tags behave differently as the scrolling happens.
You can test it here
This version uses a fancier effect but the logic behind is the same.
https://deneskellner.com/stackoverflow-examples/62623588/index.html
<!doctype html>
<html>
<style>
body.beyond-that-point {background:silver;}
div.text {padding:75vh 0px;text-align:center;}
</style>
<body>
<div class="text">
Scroll me down and the background will change
</div>
<script>
setTimeout(function() {
var amount = 100; // how many pixels before the miracle happens
var beyondClass = 'beyond-that-point'; // this class will be added
var targetSelector = 'body'; // which element to add the class to
var checkMS = 20; // check scroll position every N milliseconds
var eClass = document.querySelector(targetSelector).classList;
setInterval(function() {
var y = window.scrollY;
var c = beyondClass;
var isBeyond = !!(y>=amount)?1:0;
if(isBeyond==1) if(!eClass.contains(c)) eClass.add(c);
if(isBeyond==0) if( eClass.contains(c)) eClass.remove(c);
},checkMS);
},1);
</script>
</body>
</html>
Note: there are better ways to check DOM readiness but for simplicity I used setTimeout here. Feel free to change it.
I am creating a chat using Ajax requests and I'm trying to get messages div to scroll to the bottom without much luck.
I am wrapping everything in this div:
#scroll {
height:400px;
overflow:scroll;
}
Is there a way to keep it scrolled to the bottom by default using JS?
Is there a way to keep it scrolled to the bottom after an ajax request?
Here's what I use on my site:
var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;
This is much easier if you're using jQuery scrollTop:
$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);
Try the code below:
const scrollToBottom = (id) => {
const element = document.getElementById(id);
element.scrollTop = element.scrollHeight;
}
You can also use Jquery to make the scroll smooth:
const scrollSmoothlyToBottom = (id) => {
const element = $(`#${id}`);
element.animate({
scrollTop: element.prop("scrollHeight")
}, 500);
}
Here is the demo
Here's how it works:
Ref: scrollTop, scrollHeight, clientHeight
using jQuery animate:
$('#DebugContainer').stop().animate({
scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);
Newer method that works on all current browsers:
this.scrollIntoView(false);
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));
Works from jQuery 1.6
https://api.jquery.com/scrollTop/
http://api.jquery.com/prop/
alternative solution
function scrollToBottom(element) {
element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
}
smooth scroll with Javascript:
document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });
If you don't want to rely on scrollHeight, the following code helps:
$('#scroll').scrollTop(1000000);
Java Script:
document.getElementById('messages').scrollIntoView(false);
Scrolls to the last line of the content present.
My Scenario: I had an list of string, in which I had to append a string given by a user and scroll to the end of the list automatically. I had fixed height of the display of the list, after which it should overflow.
I tried #Jeremy Ruten's answer, it worked, but it was scrolling to the (n-1)th element. If anybody is facing this type of issue, you can use setTimeOut() method workaround. You need to modify the code to below:
setTimeout(() => {
var objDiv = document.getElementById('div_id');
objDiv.scrollTop = objDiv.scrollHeight
}, 0)
Here is the StcakBlitz link I have created which shows the problem and its solution : https://stackblitz.com/edit/angular-ivy-x9esw8
If your project targets modern browsers, you can now use CSS Scroll Snap to control the scrolling behavior, such as keeping any dynamically generated element at the bottom.
.wrapper > div {
background-color: white;
border-radius: 5px;
padding: 5px 10px;
text-align: center;
font-family: system-ui, sans-serif;
}
.wrapper {
display: flex;
padding: 5px;
background-color: #ccc;
border-radius: 5px;
flex-direction: column;
gap: 5px;
margin: 10px;
max-height: 150px;
/* Control snap from here */
overflow-y: auto;
overscroll-behavior-y: contain;
scroll-snap-type: y mandatory;
}
.wrapper > div:last-child {
scroll-snap-align: start;
}
<div class="wrapper">
<div>01</div>
<div>02</div>
<div>03</div>
<div>04</div>
<div>05</div>
<div>06</div>
<div>07</div>
<div>08</div>
<div>09</div>
<div>10</div>
</div>
You can use the HTML DOM scrollIntoView Method like this:
var element = document.getElementById("scroll");
element.scrollIntoView();
Javascript or jquery:
var scroll = document.getElementById('messages');
scroll.scrollTop = scroll.scrollHeight;
scroll.animate({scrollTop: scroll.scrollHeight});
Css:
.messages
{
height: 100%;
overflow: auto;
}
Using jQuery, scrollTop is used to set the vertical position of scollbar for any given element. there is also a nice jquery scrollTo plugin used to scroll with animation and different options (demos)
var myDiv = $("#div_id").get(0);
myDiv.scrollTop = myDiv.scrollHeight;
if you want to use jQuery's animate method to add animation while scrolling down, check the following snippet:
var myDiv = $("#div_id").get(0);
myDiv.animate({
scrollTop: myDiv.scrollHeight
}, 500);
I have encountered the same problem, but with an additional constraint: I had no control over the code that appended new elements to the scroll container. None of the examples I found here allowed me to do just that. Here is the solution I ended up with .
It uses Mutation Observers (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) which makes it usable only on modern browsers (though polyfills exist)
So basically the code does just that :
var scrollContainer = document.getElementById("myId");
// Define the Mutation Observer
var observer = new MutationObserver(function(mutations) {
// Compute sum of the heights of added Nodes
var newNodesHeight = mutations.reduce(function(sum, mutation) {
return sum + [].slice.call(mutation.addedNodes)
.map(function (node) { return node.scrollHeight || 0; })
.reduce(function(sum, height) {return sum + height});
}, 0);
// Scroll to bottom if it was already scrolled to bottom
if (scrollContainer.clientHeight + scrollContainer.scrollTop + newNodesHeight + 10 >= scrollContainer.scrollHeight) {
scrollContainer.scrollTop = scrollContainer.scrollHeight;
}
});
// Observe the DOM Element
observer.observe(scrollContainer, {childList: true});
I made a fiddle to demonstrate the concept :
https://jsfiddle.net/j17r4bnk/
Found this really helpful, thank you.
For the Angular 1.X folks out there:
angular.module('myApp').controller('myController', ['$scope', '$document',
function($scope, $document) {
var overflowScrollElement = $document[0].getElementById('your_overflow_scroll_div');
overflowScrollElement[0].scrollTop = overflowScrollElement[0].scrollHeight;
}
]);
Just because the wrapping in jQuery elements versus HTML DOM elements gets a little confusing with angular.
Also for a chat application, I found making this assignment after your chats were loaded to be useful, you also might need to slap on short timeout as well.
Like you, I'm building a chat app and want the most recent message to scroll into view. This ultimately worked well for me:
//get the div that contains all the messages
let div = document.getElementById('message-container');
//make the last element (a message) to scroll into view, smoothly!
div.lastElementChild.scrollIntoView({ behavior: 'smooth' });
small addendum: scrolls only, if last line is already visible. if scrolled a tiny bit, leaves the content where it is (attention: not tested with different font sizes. this may need some adjustments inside ">= comparison"):
var objDiv = document.getElementById(id);
var doScroll=objDiv.scrollTop>=(objDiv.scrollHeight-objDiv.clientHeight);
// add new content to div
$('#' + id ).append("new line at end<br>"); // this is jquery!
// doScroll is true, if we the bottom line is already visible
if( doScroll) objDiv.scrollTop = objDiv.scrollHeight;
Just as a bonus snippet. I'm using angular and was trying to scroll a message thread to the bottom when a user selected different conversations with users. In order to make sure that the scroll works after the new data had been loaded into the div with the ng-repeat for messages, just wrap the scroll snippet in a timeout.
$timeout(function(){
var messageThread = document.getElementById('message-thread-div-id');
messageThread.scrollTop = messageThread.scrollHeight;
},0)
That will make sure that the scroll event is fired after the data has been inserted into the DOM.
This will let you scroll all the way down regards the document height
$('html, body').animate({scrollTop:$(document).height()}, 1000);
You can also, using jQuery, attach an animation to html,body of the document via:
$("html,body").animate({scrollTop:$("#div-id")[0].offsetTop}, 1000);
which will result in a smooth scroll to the top of the div with id "div-id".
Scroll to the last element inside the div:
myDiv.scrollTop = myDiv.lastChild.offsetTop
You can use the Element.scrollTo() method.
It can be animated using the built-in browser/OS animation, so it's super smooth.
function scrollToBottom() {
const scrollContainer = document.getElementById('container');
scrollContainer.scrollTo({
top: scrollContainer.scrollHeight,
left: 0,
behavior: 'smooth'
});
}
// initialize dummy content
const scrollContainer = document.getElementById('container');
const numCards = 100;
let contentInnerHtml = '';
for (let i=0; i<numCards; i++) {
contentInnerHtml += `<div class="card mb-2"><div class="card-body">Card ${i + 1}</div></div>`;
}
scrollContainer.innerHTML = contentInnerHtml;
.overflow-y-scroll {
overflow-y: scroll;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="d-flex flex-column vh-100">
<div id="container" class="overflow-y-scroll flex-grow-1"></div>
<div>
<button class="btn btn-primary" onclick="scrollToBottom()">Scroll to bottom</button>
</div>
</div>
Css only:
.scroll-container {
overflow-anchor: none;
}
Makes it so the scroll bar doesn't stay anchored to the top when a child element is added. For example, when new message is added at the bottom of chat, scroll chat to new message.
Why not use simple CSS to do this?
The trick is to use display: flex; and flex-direction: column-reverse;
Here is a working example. https://codepen.io/jimbol/pen/YVJzBg
A very simple method to this is to set the scroll to to the height of the div.
var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);
On my Angular 6 application I just did this:
postMessage() {
// post functions here
let history = document.getElementById('history')
let interval
interval = setInterval(function() {
history.scrollTop = history.scrollHeight
clearInterval(interval)
}, 1)
}
The clearInterval(interval) function will stop the timer to allow manual scroll top / bottom.
I know this is an old question, but none of these solutions worked out for me. I ended up using offset().top to get the desired results. Here's what I used to gently scroll the screen down to the last message in my chat application:
$("#html, body").stop().animate({
scrollTop: $("#last-message").offset().top
}, 2000);
I hope this helps someone else.
I use the difference between the Y coordinate of the first item div and the Y coordinate of the selected item div. Here is the JavaScript/JQuery code and the html:
function scrollTo(event){
// In my proof of concept, I had a few <button>s with value
// attributes containing strings with id selector expressions
// like "#item1".
let selectItem = $($(event.target).attr('value'));
let selectedDivTop = selectItem.offset().top;
let scrollingDiv = selectItem.parent();
let firstItem = scrollingDiv.children('div').first();
let firstItemTop = firstItem.offset().top;
let newScrollValue = selectedDivTop - firstItemTop;
scrollingDiv.scrollTop(newScrollValue);
}
<div id="scrolling" style="height: 2rem; overflow-y: scroll">
<div id="item1">One</div>
<div id="item2">Two</div>
<div id="item3">Three</div>
<div id="item4">Four</div>
<div id="item5">Five</div>
</div>
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have an image.
I want to show different divs as popup when user clicks on particular area of the image.
I want to do it using jquery & html.
Can any one help me with this.
Here is an example of sample solution: http://jsfiddle.net/htEvT/2/
JavaScript
$('#rabbit').click(function (e) {
var offset = $(this).offset(),
left = e.pageX - offset.left,
top = e.pageY - offset.top;
if (top > $(this).height() / 2) {
alertDiv('You\'ve cliked under the middle.', 'alert-white');
} else {
alertDiv('You\'ve cliked above the middle.', 'alert-gray');
}
});
function alertDiv(text, cssClass) {
var alrt = $('<div class="alert ' + cssClass + '">' + text + '</div>');
$(document.body).append(alrt);
alrt.click(function () {
alrt.remove();
});
}
CSS
.alert {
position: absolute;
left: 30px;
top: 30px;
width: 300px;
height: 200px;
border: 1px solid black;
}
.alert-white {
background: white;
}
.alert-gray {
background: #ccc;
}
HTML
<img src="http://www.clermontanimal.net/images/lop_rabbit_easter.jpg" id="rabbit" alt="" />
If there are any issues with my solution please let me know. :)
Use Image Map on image and attach fancy box on different sections of image. Since, you have not posted code so I can't provide coding solution for the same.
Something like below should give you an Idea how to do this:
$("img").click(function() {
$("body").append("<div class='newdiv'></div>")
})
.newdiv{width:100px; height:300px;border:1px solid red;}
My favorite is Fancybox.
I'm yet to see something it cannot do. Great documentation and widely used so if you need help there is a high chance somebody else has asked the same question, and can be resolved with a simple google.
Create a DIV named "imgbox" on the HTML page on which your thumbnail images will be shown. The DIV and the CSS element ID associated with the DIV is shown below
<div id="imgbox"></div>
the css
#imgbox
{
vertical-align : middle;
position : absolute;
border: 1px solid #999;
background : #FFFFFF;
filter: Alpha(Opacity=100);
visibility : hidden;
height : 200px;
width : 200px;
z-index : 50;
overflow : hidden;
text-align : center;
}
Here is the JavaScript code to show the popup image:
Get the left and top positions of the thumbnail image:
function getElementLeft(elm)
{
var x = 0;
//set x to elm’s offsetLeft
x = elm.offsetLeft;
//set elm to its offsetParent
elm = elm.offsetParent;
//use while loop to check if elm is null
// if not then add current elm’s offsetLeft to x
//offsetTop to y and set elm to its offsetParent
while(elm != null)
{
x = parseInt(x) + parseInt(elm.offsetLeft);
elm = elm.offsetParent;
}
return x;
}
function getElementTop(elm)
{
var y = 0;
//set x to elm’s offsetLeft
y = elm.offsetTop;
//set elm to its offsetParent
elm = elm.offsetParent;
//use while loop to check if elm is null
// if not then add current elm’s offsetLeft to x
//offsetTop to y and set elm to its offsetParent
while(elm != null)
{
y = parseInt(y) + parseInt(elm.offsetTop);
elm = elm.offsetParent;
}
return y;
}
Get the thumbnail image source, make the DIV visible, increase the height and width to the required size, and attach the image to the DIV.
function Large(obj)
{
var imgbox=document.getElementById("imgbox");
imgbox.style.visibility='visible';
var img = document.createElement("img");
img.src=obj.src;
img.style.width='200px';
img.style.height='200px';
if(img.addEventListener){
img.addEventListener('mouseout',Out,false);
} else {
img.attachEvent('onmouseout',Out);
}
imgbox.innerHTML='';
imgbox.appendChild(img);
imgbox.style.left=(getElementLeft(obj)-50) +'px';
imgbox.style.top=(getElementTop(obj)-50) + 'px';
}
Hide the DIV at mouse out.
function Out()
{
document.getElementById("imgbox").style.visibility='hidden';
}
Add a OnMouseOver client-side event call for the thumbnail images to show the popup image on mouse-over.
<img id='img1' src='images/Sample.jpg' onmouseover="Large(this)" />
If the area is square, you can place a transparent element over the desired area, and give it a simple onClick event.
Use SimpleModal
You can use the plugin SimpleModal to achieve what you wanna do.
SimpleModal is a lightweight jQuery Plugin which provides a powerful interface for modal dialog development. Think of it as a modal dialog framework. SimpleModal gives you the flexibility to build whatever you can envision, while shielding you from related cross-browser issues inherent with UI development.
Using that, you can either call an already existing div or create a modal on the fly.
Calling an existing div:
$("#element-id").modal();
Making a modal on the fly:
$.modal("<div><h1>SimpleModal</h1></div>");
Giving options:
$("#element-id").modal({options});
$.modal("<div><h1>SimpleModal</h1></div>", {options});
Demos:
More demos here: http://www.ericmmartin.com/projects/simplemodal-demos/
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am interested in the way this site has the speakers scrolling at a certain interval.
I am unsure if this is a jQuery plugin but would be keen to know/understand how this functionality is done.
Create a container element that is set to the dimensions you want to display. Then set its overflow property to hidden and give it a child that is much taller. Then use a setInterval to animate the offset from the child to the parent:
HTML --
<div id="container">
<div id="child"></div>
</div>
CSS --
#container {
position : relative;
width : 500px;
height : 300px;
overflow : hidden;
}
#child {
position : absolute;
top : 0;
left : 0;
width : 100%;
height : 900px;
}
JS --
$(function () {
var $child = $('#child'),
timer = setInterval(function () {
$child.animate({ top : '-=300' }, 500);
}, 1500);
});
Update
You can then detect if the #child element should be animated back to the beginning once its entire height has been shown:
$(function () {
var $child = $('#child'),
height = $child.height(),
interval = 300,
current = 0,
timer = setInterval(function () {
current++;
if ((current * interval) >= height) {
current = 0;
$child.stop().animate({ top : 0 }, 1000);
} else {
$child.stop().animate({ top : (current * interval * -1) }, 500);
}
}, 1500);
});
Here is a demo: http://jsfiddle.net/BH5gK/2/