ScrollTop to follow bottom of the page - javascript

I'd like my website to follow the content coming out of external source, which is loaded over time
I've tried to use
chatContainer.scrollTop = chatContainer.scrollHeight;
as my chatContainer is where the content is loaded, but it doesn't work as it should, could you give me some help with that? How to make a website follow the real-time rendered content with the view?

Whenever you add more content dynamically, just call the following on the container element.
const container = document.querySelector("#container");
container.scrollTop = container.scrollHeight;
Ensure you're calling this on the container that can scroll.
If you're using jQuery, it's quite simple and it can be animated.
$("#container").animate({ scrollTop: $("#container")[0].scrollHeight }, 100);
Note that when you call $("#container")[0].scrollHeight, you are specifying that you want the scrollHeight of the first match as a document element (rather than a jQuery selector). It's the equivalent of doing document.querySelector("#container"). The 100 at the end is the number of milliseconds the animation should take.
There is no need for the MutationObserver. You don't need an interval either. You just need to run one of the above functions whenever you add content to the page (like a new message). Make sure to run it after the content is added or it won't work.
Edit: If you're not sure, open your browser's element inspector. Click on the node in the list that you want to scroll and run the following code $0.scrollTop = $0.scrollHeight;. If it doesn't work, then you're selecting the wrong element OR you haven't set your container heights correctly.
Here's an example
let count = 0;
setInterval(function(){
document.querySelector("#conversation").innerHTML += `<div class="message">Message ${count}</div>`;
document.querySelector("#container").scrollTop = document.querySelector("#container").scrollHeight;
count++;
}, 1000);
html, body { height: 100%; margin: 0; overflow: hidden; }
#container { width: 100%; max-height: 100%; border: 1px solid black; overflow-y:auto; }
.message { width: 100%; background-color: green; min-height: 100px; border-bottom: 1px solid black; }
<div id="container">
<div id="conversation">
</div>
</div>

Related

Why adding an invisible uninteractive overlay increases performance of scroll synchronization? [Chrome]

I need to synchronise the scroll of two elements: A content area and a "header".
But when I used the scroll event to change the position of the other element with a CSS transform, there was a notable delay between the user scrolling and the header moving, which is distracting, specially on Chrome.
However, when comparing to other applications that use the same method for synchronising the scroll position, they didn't have it. After many hours trying to find why, I've finally found it: they have an invisible overlay that covers the whole scroll area, which is also not interactive (CSS pointer-events: none)
I've prepared a playground below, where the overlay is visible and doesn't cover the whole area so it can be compared easily.
At least this behaviour is happening in my machine, a Mac with Chrome, and I scroll through the trackpad gesture. There also needs to be some load, so this snippet also adds a 30ms blocking loop every 100ms to simulate one
const content = document.getElementById("content");
const header = document.getElementById("header");
// Add content
const helloes = new Array(100).fill("Hello!").join("<br /><br />");
header.innerHTML = content.innerHTML = helloes;
// Synchronize scroll of content to header by adding `transform`
content.addEventListener("scroll", (evt) => {
header.style.transform = `translateY(${-content.scrollTop}px)`;
});
// Simulates performance hit, either low-end computer or a component doing extra load
setInterval(() => {
let start = Date.now();
while (Date.now() < start + 30);
}, 120);
.main {
position: relative;
display: flex;
}
.main>div {
overflow: auto;
height: 200px;
padding: 10px;
border: 1px solid black;
border-radius: 5px;
white-space: nowrap;
}
#content {
padding-right: 200px;
}
#overlay {
position: absolute;
left: 160px;
top: 50px;
width: 100px;
height: 100px;
box-sizing: border-box;
background: rgba(0, 0, 0, 0.3);
pointer-events: none;
}
<div class="main">
<div>
<div id="header">
</div>
</div>
<div id="content">
</div>
<div id="overlay"></div>
</div>
As it can be quite tricky to reproduce, I've recorded this behaviour in this image
It's quite subtle, but as you can see, when I'm scrolling with the mouse over the scroll area, there's a visible lag. If I'm scrolling instead on top of the uninteractive overlay, the scroll synchronization is perfect.
However, I totally can't understand why this happens - What is the reason adding an overlay and scrolling with the mouse on top of it improves the performance?

resizing a div element for a timeframe after a button is clicked. Do i use javascript or is there an easier way

Hi i a wondering what is the best way to resize a div for a time frame say 5 seconds after a button is clicked. what is the best solution to do this javascript or jquery
You will have to use javascript in order to do anything on the button click.
If it was me - I would add a class to the div on the click, and set a time out to remove the class. The class would have the altered styling that would affect the size of the div. In this demo - I am making the target div twice as big for a time of 2 seconds and then reoving the class to return the div back to ormal.
Note that there are numerous ways to alter the size of the div, but you will need to use javascript to trigger them. You don't need the jQuery library just this though- straight js can do it. You should investigate some of the funky CSS ways to affecting DOM elements to get a nice smooth transition or altertion.
function alterSize(type) {
var targetDiv = document.querySelector("#target-div");
targetDiv.classList.add(type);
setTimeout(function(){
targetDiv.classList.remove(type);
}, 2000)
}
#target-div {
height: 100px;
width: 100px;
border: solid 1px blue;
background: #efefef;
transition: all 0.5s ease-in-out;
}
#target-div.small {
height: 50px;
width: 50px;
}
#target-div.large {
height: 200px;
width: 200px;
}
<button type="button" onclick="alterSize('small')">Click me to decrease the size</button>
<button type="button" onclick="alterSize('large')">Click me to increase the size</button>
<hr/>
<div id="target-div">

jQuery: using a div embedded in a JavaScript variable as a jQuery selector

I have a jQuery custom scrollbar, and I invoke it like this:
<script>
(function($){
$(window).on("load",function(){
$(".main_text,#C2,.png_container").mCustomScrollbar();
});
})(jQuery);
That works correctly for all of the page elements except .png_container, but unlike the other sections, that section is only used in a JavaScript variable that is used to substitute text in a placeholder ID, and I think that's where the problem is.
Here is how it's called from an "onclick" button event:
<div class="main_text">
<div id="C2">Main Text</div>
</div>
if (type == 101) {
var X = "<header>First Section</header><br>A classic example of good form/<br><br>More information<ul type=\"circle\"><li>Element Point 1<br></li><li>Element Point 1</li></ul><i><span class=\"span_01\">So much better</i></span><br><br><div class=\"png_container\"><img class=\"png_format\" src=\"images/Element 001.png\"></div>"}
document.querySelector("#C2").innerHTML = X;}
The png_container has a separate set of scroll bars, but they are not replaced by the custom scroll bars (the other page sections do get the custom scroll bars).
Here is the relevant css:
.png_container{
overflow: auto;
overflow-y: auto;
overflow-x: auto;
height: 400px;
width: 800px;
border: 2px solid;
border-color: green;
}
#C2{
color:#DBDBDB;
font-family: camphorW04-Thin,calibri,arial;
font-size: 14pt;
text-indent: 0px;
width: auto;
margin: auto;
margin-left: 20px;
margin-right: 250px;
}
So my question is: how can I replace the scroll bars on a section that is embedded in a JavaScript variable, as shown above?
My research has found some similar questions, but none that answer this specific question, so I hope somebody knows the answer. Thanks very much for any ideas.
You initialize the mCustomScrollbar plugin on load this way:
$(window).on("load",function(){
$(".main_text,#C2,.png_container").mCustomScrollbar();
});
The two first selectors have matching elements at this moment. But there is no existing element to match the last selector since .png_container is appended on click.
So you can safely remove .png_container from the load handler...
And initialise mCustomScrollbar on .png_container when it exists.
$(window).on("load",function(){
$(".main_text,#C2").mCustomScrollbar(); // Remove .png_container
});
$(".something").on("click",function(){
if (type == 101) {
var X = "<header>First Section</header><br>A classic example of good form/<br><br>More information<ul type=\"circle\"><li>Element Point 1<br></li><li>Element Point 1</li></ul><i><span class=\"span_01\">So much better</i></span><br><br><div class=\"png_container\"><img class=\"png_format\" src=\"images/Element 001.png\"></div>"}
document.querySelector("#C2").innerHTML = X;
$(".png_container").mCustomScrollbar(); // Add this.
}

Scroll a div when focused on an internal div

I need to make a scrollable div, scroll even if the mouse is upon the content (inside the scrollable div), and not just beside it (Where it is blank). This is what I have so far:
var main = document.getElementById('main-site');
var maxTop = main.parentNode.scrollHeight-main.offsetHeight;
main.parentNode.parentNode.onscroll = function() {
main.style.top = Math.min(this.scrollTop,maxTop) + "px";
}
In Chrome is ok
In IE8+ is ok (i know a hack)
In Safari the content shakes a lot when i scroll, can i fix that? (I want fix this)
Working fiddle -> https://jsfiddle.net/8oj0sge4/6/
var main = document.getElementById('main-site');
var maxTop = main.parentNode.scrollHeight - main.offsetHeight;
main.parentNode.parentNode.onscroll = function() {
main.style.top = Math.min(this.scrollTop, maxTop) + "px";
}
#wrapper {
width: 100%;
height: 1500px;
border: 1px solid red;
padding-top: 380px;
}
#wrapper .container {
border: 1px solid green;
width: 100%;
height: 500px;
overflow: scroll;
}
#wrapper .container-scroll {
height: 1500px;
width: 100%;
border: 1px solid yellow;
position: relative;
}
#wrapper .main {
width: 200px;
height: 500px;
background: black;
overflow: scroll;
position: absolute;
color: white;
left: 50%;
margin-left: -100px;
margin-top: 10px;
}
<div id="wrapper">
<div class="container">
<div class="container-scroll">
<div id="main-site" class="main">
My goals is to make the div container scroll also when the mouse is hover this div in safari, in Google and IE8 i already know how to make work, but safari is shaking a lot!
</div>
</div>
</div>
</div>
Thank you guys.
I hope this demo helps you out to make the div content scroll when mouse hover and when mouse out of the div.
<html>
</head>
<style>
.mydiv
{height: 50px;width: 100px; overflow-y: scroll; }
</style>
<script>
function loadpage()
{ document.getElementById('marquee1').stop(); }
function marqueenow()
{ document.getElementById('marquee1').start(); }
</script>
</head>
<body onload="loadpage()">
<marquee id="marquee1" class="mydiv" onmouseover="marqueenow()" onmouseout="loadpage()" behavior="scroll" direction="up" scrollamount="10">
This is my test content This is my test content This is my test content This is my test content This is my test content This is my test content This is my test
content This is my test content This is my test content This is my test content This is my test content This is my test content This is my test content This is my test content This is my test content This is my test content
</marquee>
</body>
</html>
you just add this js file to get a smooth scrolling effect.
https://github.com/nathco/jQuery.scrollSpeed
live deomo
http://code.nath.co/scrollSpeed
Not 100% sure what you are up to but you can get the fixed position with css "fixed". It will stay where you put it. The following css fixes to the bottom of the page.
.fixed {
bottom: 0;
left: 0;
position: fixed;
right: 0;
top: auto;
}
There is already an answer on scroll position:
How to get scrollbar position with Javascript?
I don't know important is that content, and by this I mean if it needs to stay selectable.
If not a pretty good solution would be to use #wrapper .main{ pointer-events: none; }, meaning that the content will not get any events from mouse and it would go through it to the next element behind it - in your case the scroll would go dirrectly to #wrapper.
Safari does this because every browser has its own scrolling. If you have a fixed header on a phone it acts bouncy and if you do this on a PC it acts normal. Explorer scrolls smooth and Chrome scrolls right to the place without a smooth transition.
The reason why your #main-site is "jiggling" is because the browser keep "repaint" the position of this element.
One Trick to solve this is called Debounce Function, (you may also google it to see other variations.) The basic idea is to delay the scroll event handler to clear out those untriggered callbacks.
In your case, you may do something like this:
main.parentNode.parentNode.onscroll = function(event) {
debounce(offsetting, 10);
}
function offsetting() {
main.style.top = Math.min(main.parentNode.parentNode.scrollTop,maxTop) + "px";
}
function debounce(method, delay) {
clearTimeout(method._tId);
method._tId= setTimeout(function(){
method();
}, delay);
}
If you keep seeing the jiggling issue, you can simply edit the delay parameter (i.e, change 10 to 50). The downside for that is your #main-site element will be 'cut off the top` for a while, depending on your delay settings.
Since your code works perfectly on Chrome and IE, there might be a bug on scrollHeight or offsetHeight attribute on Safari. I recommend you to use getBoundingClientRect for calculating element position since this method is more reliable and accurate.
var maxTop = main.parentNode.getBoundingClientRect().height - main.getBoundingCLientRect().height;

How to resize a div to clients viewport height?

Ok, so i want to have a series of divs which are the exact width and height of the user's browser window, regardless of the screen size. I can easily make the divs stretch horizontally with "width: 100%;" but i cant work out how to make the height stretch itself. I am guessing that i need to use some bit of javascript to judge the height, and then another piece to resize the seperate divs. Unfortunately I am a complete javascript n00b and after two hours of seemingly fruitless searching and coming up with about 100 "solutions" this was as far as id gotten (Im sure that at some point I have probably been closer to the answer):
var viewportHeight = "height:" + document.documentElement.clientHeight;
getElementById('section-1').setAttribute('style', viewportHeight);
<div class="section" id="section-1"></div>
<div class="section" id="section-2"></div>
<div class="section" id="section-3"></div>
edit:
ah i should be more clear, im attempting to have all three divs take up the entire screen, so you have to scroll down to see each one - almost like seperate slides. The idea is that each one takes up the entire screen so you cant see the next section until you scroll down, rather than having three divs which take up a third of the screen.
If you haven't already tried it, you'll want to look at parent:child inheritance of elements within the DOM by way of using CSS.
What I want to STRESS is that everyone giving you JS hacks to accomplish this is not only providing you with overkill (YOU did ask for a JavaScript solution, so they gave it to you!), but it's also a deviation from standards. HTML is for structure, CSS is for presentation, and JavaScript is for behavioral aspects... setting a div to the width of the viewport on load is a PRESENTATION aspect and should be done in CSS... not JavaScript. If you were trying to change the width based on events or user interaction, then yes JavaScript is your friend... but stick with just HTML and CSS for now.
The trick is that most elements have an undefined height - and height is later defined by the content that the element holds.
If you want to 'trick' an element into having a height other than what it wants to default to, you'll have to explicitly define it. Since you want to inherit your height from the viewport, you'll have to define the height at the top and bring it down...
You might be in luck and can avoid JavaScript altogether (unnecessary). Just use CSS.
Try something like:
html, body {
height: 100%;
width: 100%;
}
Now, when you try to set your div's later on, specify width: 100% and the height gets inherited from the html --> body --> div.
Try that and see if that solves your problem - if not, point us to a website, a pastebin, or a SOMETHING with code in it that we can just show you how to do it (whereas what you posted for code was an attempt in JavaScript which is only 1 part of the code - post the full thing either to a server or temp site like pastebin).
Here is some sample code I wrote (tested in Chromium):
The HTML:
<html>
<head>
<title>Test Divs at 100%</title>
<link rel="stylesheet" type="text/css" href="divtest.css"
</head>
<body>
<div class="test1">aef</div>
<div class="test2">aef</div>
<div class="test3">aef</div>
</body>
</html>
The CSS:
html, body {
width: 100%;
height: 100%;
background-color: #793434;
padding: 0;
margin: 0;
}
div {
height: 100%;
width: 100%;
}
.test1 {
background-color: #E3C42E;
}
.test2 {
background-color: #B42626;
}
.test3 {
background-color: #19D443
}
try this
div#welcome {
height: 100vh;
background: black;
color: white;
}
div#projects {
height: 100vh;
background: yellow;
}
<div id="welcome">
your content on screen 1
</div>
<div id="projects">
your content on screen 2
</div>
it should work for you, but little support in IE
A bit of jQuery should do it:
$(document).ready(function() {
var window_height = $(window).height();
$('#section-1").height(window_height);
});
And if you want to keep 100% height on window resize:
$(document).ready(function() {
function viewport_height() {
var window_height = $(window).height();
$('#section-1").height(window_height);
}
viewport_height();
$(window).resize(function() {
viewport_height();
});
});
try this
window.onload = init;
function init()
{
var viewportHeight = "height:" + document.documentElement.clientHeight+"px;";
document.getElementById('section-1').setAttribute('style', viewportHeight);
}
Here is a script free solution, just CSS. This assumes that the divs are directly in the body element or a parent with position absolute and the parent has no padding.
#section-1 {
position: absolute;
height: 100%;
width: 100%;
background: #ff0000;
}
#section-2 {
position: absolute;
width: 100%;
top: 100%;
height: 100%;
background: #00ff00;
}
#section-3 {
position: absolute;
width: 100%;
top: 200%;
height: 100%;
background: #0000ff;
}
See fiddle: http://jsfiddle.net/QtvU5/1/

Categories