How to modify element upon it exiting "sticky" state? - javascript

I've got an element stickied to the bottom of the viewport. I am trying to have it change text upon reaching its "destination", i.e. when it stops sticking.
I found a somewhat relevant solution elsewhere online, but I can't quite get it to work... It almost does the trick, but it only goes into effect once the element comes in contact with the top of the viewport. Whereas I want it to turn pink once it stops sticking, immediately when it touches the blue element.
I've looked around for about a week now and I still can't find a way to make this happen, nor have I had any success through pure trial and error...
Hopefully some of you wizards here know how I can achieve this.
Link to codepen: https://codepen.io/darkwing/pen/WNwVXKx
Please ignore that the element starts out pink below if you don't use the link above.
const el = document.querySelector(".myElement")
const observer = new IntersectionObserver(
([e]) => e.target.classList.toggle("is-pinned", e.intersectionRatio < 1),
{ threshold: [1] }
);
observer.observe(el);
#parent {
height: 2000px;
}
.filler {
background-color: green;
height: 500px;
}
.myElement {
width: 300px;
height: 200px;
background-color: red;
position: sticky;
bottom: 0;
}
.otherElement {
width: 300px;
height: 200px;
background-color: blue;
}
/* styles for when the header is in sticky mode */
.myElement.is-pinned {
background-color: pink;
}
<div id="parent">
<div class="filler"></div>
<div class="myElement"></div>
<div class="otherElement"></div>
</div>

Related

How do I hide a scrollbar after scrolling and make it visible again on scroll?

My intention is to hide my scrollbar (i.e, hidden by SLIDING TO THE RIGHT), after scrolling (let's say, like 2 or 3 seconds after I'm done scrolling)
And to make it visible again, soon as I start scrolling (i.e, visible by SLIDING IN FROM THE RIGHT)
VIEW CODE SNIPPET:
div::-webkit-scrollbar {
width: 8px;
/* helps remove scrollbar which resizes or shifts list items */
/* display: none; */
}
div::-webkit-scrollbar-track {
background-color: #444444;
}
div::-webkit-scrollbar-button:vertical:increment {
background-color: rgba(108, 92, 231, 0.65);
}
div::-webkit-scrollbar-button:vertical:decrement {
background-color: rgba(108, 92, 231, 0.65);
}
div::-webkit-scrollbar-thumb {
background-color: rgba(108, 92, 231, 0.7);
border-radius: 10px;
}
div::-webkit-scrollbar-thumb:hover {
background-color: rgba(108, 92, 231, 1);
}
div {
width: 500px;
height: 300px;
background-color: #ececec;
overflow: auto;
}
<div>
<p style="height: 300vh;">Just some tall paragraph to force DIV scrollbars....</p>
</div>
Please help me everyone (I'D BE SO GRATEFUL!)
:D
Since CSS does not have timeouts and clearing of timeouts - Use JavaScript
Use Element.classList to add and remove a class
Use setTimeout() set at 2500ms, but every time a scroll event is triggered remove the previous pending timeout using clearTimeout. Logically, after you finished scrolling the last timeout that was set will, after 2.5s trigger finally the class removal.
Use a CSS class like .is-scrolling to there define the desired scrollbar styles (which otherwise are transparent by default)
const showScrollbars = (evt) => {
const el = evt.currentTarget;
clearTimeout(el._scrolling); // Cancel pending class removal
el.classList.add("is-scrolling"); // Add class
el._scrolling = setTimeout(() => { // remove the scrolling class after 2500ms
el.classList.remove("is-scrolling");
}, 2500);
};
document.querySelectorAll("[data-scrollbars]").forEach(el => {
el.addEventListener("scroll", showScrollbars);
});
[data-scrollbars] {
width: 500px;
height: 180px;
background-color: #ececec;
overflow: auto;
}
[data-scrollbars]::-webkit-scrollbar {
width: 8px;
height: 8px;
}
[data-scrollbars]::-webkit-scrollbar-track {
background-color: transparent;
}
[data-scrollbars]::-webkit-scrollbar-thumb {
background-color: transparent;
border-radius: 10px;
}
[data-scrollbars].is-scrolling::-webkit-scrollbar-track {
background-color: #777;
}
[data-scrollbars].is-scrolling::-webkit-scrollbar-thumb {
background-color: gold;
}
<div data-scrollbars>
<p style="height: 300vh;">
Just some tall paragraph to force DIV scrollbars...<br>
Scroll me! (<<< PS: See the problem?!)
</p>
</div>
I would highly not advise you hide scrollbars. Scrollbars are a visual hint to the user that there's actually content to be scrolled. Do a simple A/B testing. For half of your visitors show the scrollbar. For the other half, do that funky stuff - and don't be surprised that your click trough-rate for the below-the-fold portion of the app (or element) has fewer-to-none interactions by that second group of users.
I am thinking about what if user do not have any mouse wheel for scrolling and if user scroll with the actually using scroll bar.
Anyway please search for slim fading scroll bar example at google. You will find some examples for the slim scroll maybe it’s not invisible but it’s transparent and have a good shape.

How to scroll MULTIPLE scrollbars at the same time

When I scroll the wrapper div the 2 images should also scroll together with it but it seems only the 2 images sync together but not the wrapper
The 2 images should sync with the body's scrollbar
$(function(){
$('.linked').scroll(function(){
$('.linked').scrollTop($(this).scrollTop());
})
})
#left { width: 300px; height: 400px; overflow: scroll; float: left; }
#right { width: 300px; height: 400px; overflow: scroll; float: left; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<div id="left" class="linked">
<img src="http://upload.wikimedia.org/wikipedia/commons/5/51/Eiffel_Tower_(72_names).jpg">
</div>
<div id="right" class="linked">
<img src="http://upload.wikimedia.org/wikipedia/commons/5/51/Eiffel_Tower_(72_names).jpg">
</div>
This might help
let l = document.getElementById(".left");
let r = document.getElementById(".right");
l.addEventListener("scroll", function () {
r.scrollTop = l.scrollTop;
});
l.addEventListener("scroll", function () {
r.scrollTop = l.scrollTop;
});
If I understood correctly you're question is how to sync a set of scroll bars including the window scroll bar? This is possible and I will demonstrate for education purposes only however this is not something I would personally recommend.
Manipulating the browser window scroll bar can create a poor user experience as it interferes with the expected behavior of the scroll bar. Additionally, scrollbar manipulation can cause unexpected behavior and may not work consistently across different browsers and devices, leading to a fragmented user experience.
This example does not take into consideration the dimensions of the browser window and elements with scroll bars so be warned that it might not work as expected.
// Pseudo code
// 1. Query the scroll bars you want to sync
// 2. Add event listener to each of them
// 3. In the event listener, set the scroll position of the other scroll bar(s) to the same value
// Step 1
const scrollBarContainers = [
...document.querySelectorAll('.scrollable'),
document // Include document for window scrolling
];
// Step 2
scrollBarContainers.forEach(container => {
container.addEventListener('scroll', syncScrolls);
});
// Step 3
function syncScrolls(e) {
scrollBarContainers.forEach(container => {
if (container !== e.target) {
// The document element doesn't directly have a scrollLeft property.
// It's on the scrollingElement. The other elements have it directly.
if (container.scrollingElement) {
container.scrollingElement.scrollLeft = e.target.scrollLeft;
} else if (e.target.scrollingElement) {
container.scrollLeft = e.target.scrollingElement.scrollLeft;
} else {
container.scrollLeft = e.target.scrollLeft;
}
}
});
}
.container {
height: 100px;
border: 1px solid gray;
width: 900px;
margin-bottom: 1em;
overflow: auto;
}
span {
display: inline-block;
width: 1200px;
height: 50px;
background-color: red;
}
<div class="container scrollable"><span></span></div>
<div class="container scrollable"><span></span></div>

How do I prevent scroll back up with JavaScript or jQuery?

I have a webpage where there is a full height intro image. Underneath this image is the main body of the site with a regular site header at the top, I'm trying to create an effect where once the user scrolls down to the site header, they cannot scroll back up to view the intro image.
CSS Classes:
Main Intro Image: .cq-fullscreen-intro
Site Header: .nav-down
I had a poke around on StackOverflow but I can't find anything that addresses this circumstance, can anyone point me in the right direction to achieve this using jQuery?
you can use JQuery scrollTop function like this
$(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
// set the height in pixels
if (scroll >= 200) {
// after the scroll is greater than height then you can remove it or hide it
$(".intro-image").hide();
}
});
});
So instead of scrolling, I personally think it would be better to have it be actionable. Forcing the user to manually do the transition (and all in between states) is a bad idea. If the user scrolls half way, and see's something actionable (menu, button, input field) is it usable? If it is, what happens if they submit... very awkward. If it isn't usable, how do they know when it is? How do they know it's because they haven't scrolled all the way. It's very poor user experience.
In the following example, I've created a pseudo-screenport for you to see what's actually going on. The .body container in your real site would be the body element.
Code Pen Example
$(document).ready(function(){
$('.splash-screen').on('click', function(){
$('.splash-screen').addClass("is-hidden");
});
})
html, body{
background: #eee;
margin: 0;
padding: 0;
}
.flex-root {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.web-container {
width: 640px;
height: 480px;
background: #fff;
}
.body {
font-size: 0; // this is only to prevent spacing between img placholders
position: relative;
}
.splash-screen{
position: absolute;
transition: transform 1s ease-in-out;
}
.splash-screen .fa {
position: absolute;
z-index: 1;
font-size: 24px;
color: #fff;
left: 50%;
bottom: 15px;
}
.splash-screen.is-hidden {
transform: translateY(-110%);
transition: transform 1s ease-in-out;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="flex-root">
<div class="web-container">
<div class="body">
<div class="splash-screen">
<img src="https://via.placeholder.com/640x480?text=Splash+Screen"/>
<i class="fa fa-chevron-circle-up"></i>
</div>
<img src="https://via.placeholder.com/640x60/cbcbcb?text=Menu"/>
<img src="https://via.placeholder.com/640x420/dddddd?text=Site Body"/>
<div>
</div>
</div>
While its not direclty preventing you from scrolling up and its not jQuery, I would suggest to remove/hide the element once its out of view.
You could get the current scroll position, relative to the top of the page, and check if its greater than the elements height:
const target = document.getElementById('my-target')
const targetHeight = target.getBoundingClientRect().height
const scrollEventListener = () => {
if (
document.body.scrollTop > targetHeight ||
document.documentElement.scrollTop > targetHeight
) {
target.remove()
window.removeEventListener('scroll', scrollEventListener)
document.documentElement.scrollTop = 0
}
}
window.addEventListener('scroll', scrollEventListener)
Here is a codepen https://codepen.io/bluebrown/full/aboagov

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;

javascript window scroll issue

I am working on javascript scroll. I have following html code
JSFIDDLE
<div class="wrapper">
<div class="red div current"></div>
<div class="blue div"></div>
<div class="green div"></div>
<div class="yellow div"></div>
</div>
In above code I have four div tags red, blue, green and yellow. All of them are position in following css.
html, body {
height: 100%;
}
.wrapper {
overflow: hidden;
height: 100%;
}
.div {
position: relative;
height: 100%;
}
.red {
background: red;
}
.blue {
background: blue;
}
.green {
background: green;
}
.yellow {
background: yellow;
}
In above html and css the red div tag is the current one which means user is seeing the red div tag on the screen. Now what I am trying to do is when user scroll over window once, then the next div tag i.e. blue will be animated and moved to the top and will become visible to the user whereas the red div tag will be behind the blue one. This same process goes for both green and yellow.
The problem is that when user scroll once then the div tag should animate however my current javascript code is keep reading the scroll and animating the div tags one after another. What I want is when user scroll once then scroll should be disabled until the blue div tag is animated. Then scroll should be enabled. Again when user scroll second time, the scroll should disable until the green div tag completes its animation. Same goes for yellow.
How can I achieve above?
Here is my javascript
$(window).on("scroll", function () {
var next = $('.current').next();
var height = next.outerHeight();
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().removeClass('current');
$(this).addClass('current');
});
});
Please have a look on update JsFiddle
$(window).on("scroll", function () {
var next = $('.current').next();
var height = $('.current').outerHeight();
$('.current').prevAll().each(function(){
height += $(this).outerHeight();
});
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().css('top','');
$(this).prev().toggleClass('current');
$(this).toggleClass('current');
});
});
The main reason your example wasn't working as expected is because you were relatively positioning the divs, and not moving them to the correct spot.
Working JSFiddle:
http://jsfiddle.net/seanjohnson08/rVVuc/6/
.wrapper {
overflow: hidden;
height: 100%;
position: relative;
}
.div {
position: absolute;
height: 100%;
width: 100%;
top: 100%;
}
.current{
top: 0;
}
If you are looking for a way to limit the amount of scroll events fired, try throttling: http://benalman.com/projects/jquery-throttle-debounce-plugin/. My solution doesn't require this, because no matter how many times it is firing the scroll event, it only ever tells jquery to animate to top:0, there's no chance of it animating past that.

Categories