Setting CSS value limits of the window scrolling animation
You can not use animate()
method with scroll function it will create conflict because scroll value will change always and jQuery can not infinite repeat same animation. Stop won't rescue this issue either, or i cound't manage to do it.
And i suggest to use variation in if
statements.
Here is not working animate sample with animate usage.
Here is same example working with css method.
$(window).scroll(function() {
var scrollVal = $(this).scrollTop();
if ( scrollVal > offset.top) {
$sidebar.css({
'margin-top': (($window.scrollTop() - offset.top) + topPadding) + 'px'
//added +'px' here to prevent old internet explorer bugs
});
} else {
$sidebar.css({'margin-top':'0px'});
}
});
Note: if you want to expand your if statements with else if
, don't use else
, it will create conflict too. Bealive me i am really expreienced with this issue.
UPDATE:
You can change your approuch to calculations of the limits too. I presume you want to fix the nav and your html is like this:
<div class="wrapper">
<div class="header">header</div>
<span id="subnav">hold this</span>
</div>
and jQuery calculations should be like this:
Here is working jsFiddle.
$(document).ready(function() {
$(window).scroll(function() {
var headerH = $('.header').outerHeight(true);
//this will calculate header's full height, with borders, margins, paddings
console.log(headerH);
var scrollVal = $(this).scrollTop();
if ( scrollVal > headerH ) {
//when scroll value reach to your selector
$('#subnav').css({'position':'fixed','top' :'0px'});
} else {
$('#subnav').css({'position':'static','top':'0px'});
}
});
});
Prevent body scrolling but allow overlay scrolling
Theory
Looking at current implementation of the pinterest site (it might change in the future), when you open the overlay, a noscroll
class is applied to the body
element (setting overflow: hidden
) making the body
no longer scrollable.
The overlay created on-the-fly or already injected in the page and made visible via display: block
— it makes no difference – has position : fixed
and overflow-y: scroll
, with top
, left
, right
and bottom
properties set to 0
: this style makes the overlay fill the whole viewport (but now we are in 2022, so you may use inset: 0
instead).
The div
inside the overlay is in position: static
so the vertical scrollbar is related to that element. This is resulting in a scrollable but fixed overlay.
When you close the overlay, you have to hide it (using display: none
) and you could even remove the node via javascript (or just the content inside, it's up to you but also depends on the nature of the content).
The final step is to also remove the noscroll
class applied to the body
(so the overflow
property gets back to the value it had previously)
Code
Codepen Example
(it works by changing the aria-hidden
attribute of the overlay in order to show and hide it and to increase its accessibility).
Markup
(open button)
<button type="button" class="open-overlay">OPEN LAYER</button>
(overlay and close button)
<section class="overlay" aria-hidden="true" tabindex="-1">
<div>
<h2>Hello, I'm the overlayer</h2>
...
<button type="button" class="close-overlay">CLOSE LAYER</button>
</div>
</section>
CSS
.noscroll {
overflow: hidden;
}
.overlay {
position: fixed;
overflow-y: scroll;
inset: 0; }
[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }
Javascript (vanilla-JS)
var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]'),
openingBtt;
[].forEach.call(overlayBtts, function(btt) {
btt.addEventListener('click', function() {
/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';
/* storing a reference to the opening button */
if (overlayOpen) {
openingBtt = this;
}
/* Toggle the aria-hidden state on the overlay and the
no-scroll class on the body */
overlay.setAttribute('aria-hidden', !overlayOpen);
body.classList.toggle('noscroll', overlayOpen);
/* On some mobile browser when the overlay was previously
opened and scrolled, if you open it again it doesn't
reset its scrollTop property */
overlay.scrollTop = 0;
/* forcing focus for Assistive technologies but note:
- if your modal has just a phrase and a button move the
focus on the button
- if your modal has a long text inside (e.g. a privacy
policy) move the focus on the first heading inside
the modal
- otherwise just focus the modal.
When you close the overlay restore the focus on the
button that opened the modal.
*/
if (overlayOpen) {
overlay.focus();
}
else {
openingBtt.focus();
openingBtt = null;
}
}, false);
});
/* detect Escape key when the overlay is open */
document.body.addEventListener('keyup', (ev) => {
if (ev.key === "Escape" && overlay.getAttribute('aria-hidden') === 'false') {
overlay.setAttribute('aria-hidden', 'true');
body.classList.toggle('noscroll', false);
openingBtt.focus();
openingBtt = null;
}
})
Finally, here's another example in which the overlay opens with a fade-in effect by a CSS transition
applied to the opacity
property. Also a padding-right
is applied to avoid a reflow on the underlying text when the scrollbar disappears.
Codepen Example (fade)
CSS
.noscroll { overflow: hidden; }
@media (min-device-width: 1025px) {
/* not strictly necessary, just an experiment for
this specific example and couldn't be necessary
at all on some browser */
.noscroll {
padding-right: 15px;
}
}
.overlay {
position: fixed;
overflow-y: scroll;
inset: 0;
}
[aria-hidden="true"] {
transition: opacity 1s, z-index 0s 1s;
width: 100vw;
z-index: -1;
opacity: 0;
}
[aria-hidden="false"] {
transition: opacity 1s;
width: 100%;
z-index: 1;
opacity: 1;
}
How to change CSS when user scrolls past a certain div
What you need to do is calculate the offset height of each specific DIV with respect to the top of the page or scrollable area.
Then, using your .scroll() function, when the offset is reached (i.e. the 'div' offset matches the 'scroll' position) you can fire your animation off.
Also, (based on a slightly different offset (e.g. div offset -600px) you could 'reset' the animation if the user scrolls back up the page, past the animation. Although, this might end being annoying to the user and more work than benefit . . .
offset : http://api.jquery.com/offset/
scrollTop : http://api.jquery.com/scrolltop/
Jquery animate css on scrolling causes jitter
They are using Greensock's GSAP heavily for this, which is a great lib, but more of an enterprise solution and a decent learning curve.
A good place to start would be to check out requestAnimationFrame
and a throttling method (i used lodash for this example).
Using translateY
(or X, or 3d) helps too instead of using top
Here's a JSBin demo with HTML/CSS/JS, but here's the relevant bit:
JS
var ticking = false,
item = document.querySelectorAll('.item');
// RAF
function update() {
ticking = false;
item[0].style.transform = 'translateY('+window.scrollY+'px)';
}
function onScroll() {
ticking = ticking || requestAnimationFrame(update);
}
window.addEventListener('scroll', onScroll, false);
// Scroll Throttle
function throttled_version() {
item[1].style.transform = 'translateY('+window.scrollY+'px)';
}
window.addEventListener('scroll', _.throttle(throttled_version, 16), false);
Giving the CSS a transition
can help the fluidity as well. Just 50ms in this case since it fires repeatedly. It kind of simulates a velocity/momentum effect
Scrolling bar for messages like in Facebook messages
Sure you can do this with pure css; position property, no need jQuery.
Use css position:fixed;
on element's you don't want to scroll and use css values float:left;
or position:relative;
on content areas you want to scroll.
But if you want to stick some element's according to scroll.top
value, you need to use jQuery. I suggest to inspect these answer for it: How to build simple sticky navigation at the page bottum? and Setting CSS value limits of the window scrolling animation
jQuery code to change position of element on scroll
Here is the fixed solution. :)
It starts with getting scroll position then change the CSS of element to fixed when scrolling passes specific value (the distance between top to element start) else revert default css for element.
var sOffset = $(".sharelinks").offset().top;
var shareheight = $(".sharelinks").height() + 43;
$(window).scroll(function() {
var scrollYpos = $(document).scrollTop();
if (scrollYpos > sOffset - shareheight) {
$(".sharelinks").css({
'top': '61px',
'position': 'fixed'
});
} else {
$(".sharelinks").css({
'top': 'auto',
'position': 'relative'
});
}
});
Related Topics
Are All JavaScript Callbacks Asynchronous? If Not, How to Know Which Are
JavaScript Date Regex Dd/Mm/Yyyy
Defer Execution for Es6 Template Literals
Browser-Native JSON Support (Window.JSON)
Jquery.Parsejson Single Quote VS Double Quote
Why Is 'Replace' Property Deprecated in Angularjs Directives
Access Outside Variable in Loop from JavaScript Closure
What Is "Undefined X 1" in JavaScript
Making a JavaScript String SQL Friendly
Webhoster Inserts a JavaScript Which Brokes My Code How to Remove It
How to Prevent Page from Reloading After Form Submit - Jquery
How to Make Post Requests with the Formdata API
Fast Rectangle to Rectangle Intersection
Input Type=File Show Only Button
Using Jquery How to Get Click Coordinates on the Target Element
How to Access an SQLite Database from JavaScript