Setting CSS Value Limits of the Window Scrolling Animation

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: blockit 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



Leave a reply



Submit