If anybody could help me, I would greatly appreciate it. I am using requestAnimationFrame() to apply a vertical translate on an element with CSS, and I want the vertical translate distance to relate to the vertical scroll position. My issue is that it seems like some frames either do not call my function or do not repaint with the updated CSS when using the scroll wheel (testing with Chrome and Firefox, both up-to-date).
This is a trimmed down version (optimizations removed) to show the root of what I'm trying to do:
let sticky = document.getElementById('top');
function changePos() {
let position = window.scrollY;
sticky.style.transform = `translateY(${position}px)`;
window.requestAnimationFrame(changePos);
}
window.requestAnimationFrame(changePos);
You can see a full working demo on this upload. For some reason clicking and dragging the scrollbar doesn't miss any frames, but using the mouse wheel does. You may have to throttle CPU using dev tools to see the missed frames, or use an older computer or phone.
Thanks so much.
I have the problem to keep latest window scroll position after screen orientation has been changed.
For example, on the page
http://www.svoboda.mobi/a/27582777.html
when I scroll to the middle of the screen and then rotate from portrait to landscape or vice versa, the screen position is going to top of the page instead of to keep latest position.
It affects Android phones, iOS, and probably other devices. It's working correctly on Nokia Lumia 520.
I know, that I can use some javascript like
$(window).on(scroll, function() {
//save the current scroll position somehow
});
$(window).on("orientationchange", function(event){
//scroll window to saved position
});
but I don't want to solve that by this way. I still don't know, what is the cause of that? I think it must be some error in CSS, because when I turn off javascript, the problem still occurs. Thank you for help.
I am trying to get a div to go from 100% opacity to 0% opacity on scroll.
I made this Fiddle and it works great in a web browser, just as I'd hope. It works in mobile browsers too, but with one horrible downside.
var divs = $('.cover_image');
$(window).on('scroll', function() {
var st = $(this).scrollTop();
divs.css({
'opacity': (1 - st / 40)
});
});
(What is happening in the fiddle is the top div is going to opacity:0 as you scroll, revealing another div below it with the same background-image, but blurred. Creating the impression the same image is blurring the more you scroll)
In a web browser as you scroll the div drops in opacity progressively with a fade like affect which is great.
However in a mobile browser the change of opacity doesn't take effect until you release your finger from the the screen. So there is no progressive change of opacity. It only makes the changes visually as you release your finger from the screen, not as you scroll.
Is there a solution for this? I have tried adding in scrolling touch to my css, but it doesn't make a difference.
-webkit-overflow-scrolling: touch
Scrolling distance on mobile works very different from desktop. Even if you detect each step in the touch event, this is only half the truth. When the user releases, the site will continue to scroll for a bit while deaccelerating. This is called momentum scroll and will in most cases not be picked up by the touch event.
There are to my knowledge no perfect solution to this, since different devices handle scroll and touch very differently. There are however a few options you could look into.
Scrolling libraries
There are libraries to help you solve this problem. For instance one called scrollability that emulates scrolling to work more consistently.
Scrollability adds a good imitation of iOS native scrolling to your
mobile web apps.
Scrollability is a single script, it's small, and it has no external
dependencies. Drop it into your page, add a few CSS classes to
scrollable elements, and scroll away.
Ignore the scroll completely
Don't look at the touch or scroll events. Instead use setInterval or requestAnimationFrame with desired frequency that reports the pages current position (document.documentElement.scrollTop) at all time. Base your animation on this value instead of scroll or touch events. You might want to limit this to touch devices since it's not needed for desktop.
Write your own scroll functionality
Disable scrolling and make your own, without for instance momentum scroll, that is suited for your needs. Note that the scroll event is usually disabled on desktop if you disable scroll, but mousewheel works. I have been down this path and I would not recommend it. Instead you should probably go with the library approach at the top.
I have a situation when a fixed-size and overflow:hidden element in a browser window contains a very long image, which is basically a vertical sequence of animation frames.
The animation has to occur when a user is scrolling the window. Specifically, advance in $(window).scrollTop() implies corresponding shift in animation frames.
Simple linear dependency between scroll offset and frame number gives me excellent smooth animation on Mac OS, but Windows has a "jumpy" scroll and we instead see an immediate 'jump' from one frame to another.
Now, as though I do feel I'm going to need to detect offset delta between scroll events, and animate the frame advance accordingly using time-based iterations, the question stands: is there a way to make Windows generate a smoother change in scroll offset somewhat like Mac OS does?
Thank you.
I have a page where I'm applying a parallax effect. This is accomplished using translate3d. Now, while this works well, I'm wondering how I can override the default "steps" when scrolling with the mouse wheel?
If I scroll with the scrollbars, everything is fine. But with the mouse wheel, it's all jumpy.
I'm doing this in a pretty straight forward way:
var prefix = Modernizr.prefixed('transform');
$window.on('scroll', function(){
var scroll_top = $window.scrollTop();
if(scroll_top < forside_infographics_offset){
$_('#slider').css(prefix , "translate3d(0,"+(scroll_top/3)+"px,0)");
}
});
Now, I've seen this site where the scrolling is super smooth, also with a mouse wheel with steps on it. I've tried to look at the code, and he's using requestAnimationFrame is seems, but how he accomplish this excact scrolling effect, I'm not sure.
http://cirkateater.no/
Any ideas?
After doing a lot of research, I found a pretty easy solution :)
http://bassta.bg/demos/smooth-page-scroll/
Interestingly enough, I didn't have to alter my existing code at all. This overrides the default scroll behaviour, while leaving the event open for me to use like I would normally do.
EDIT: This is a really bad idea. Never ever hijack and override expected behavior. I guess I was overly fascinated with animations back then and overdid everything. Thankfully we all learn and expand our perceptions of good UX principles :)
Scrolling using the mouse wheel requires special handling. Reason being each mouse wheel scroll doesn't scroll the content by a certain amount of pixels. Each scroll causes your page to jump and then each jump results in the "jumpy" jittery animation as the background image is trying to position itself at these jumps.
Using a library will solve the problem most of the time, but it is also worth understanding what problems it is trying to solve under the hood.
Just for reference sakes, the mouse events are mousewheel and DOMMouseScroll
This plugin for Chrome provides the functionality necessary for this. Someone created a gist with a minified version of it. It's from a pretty old version, but I think that's fine because, as I've checked, the latest version of the plugin adds too much stuff.
A couple things with that gist though:
It checks if the browser is Chrome before initiating.
It initiates automatically.
It uses jQuery.
So I let myself create a version that addresses those points. Just add the script and call SmoothScroll.init() to start.
Edit: While testing I figured out this has a significant bug. While my version behaves (in my opinion) tremendously better than the original code, it unfortunately does not account for scrolling by other means (scroll bar/middle click and drag). Scrolling by one of these methods and then scrolling with the mouse wheel causes it to revert to wherever scroll location you were at when you last scrolled the mousewheel. I'll update when I develop a solution to this.
Kenny's referenced solution was a fine approach, but it's functionality drove me crazy. If you scroll the wheel quickly it wouldn't scroll much faster.
I improved it such that you scroll a given distance per click regardless of mouse wheel spin speed.
The reason his answer did not is because if you scroll the wheel a second time before the first animation is complete the new scroll to height is only the current scroll height plus however much it scrolls per wheel click. (So if scroll time is .5 seconds and you scroll a second time after .25 seconds then it will scroll 1.5 times the wheel scroll distance instead of 2 times that distance)
It's late at night, I hope that makes sense.
Regradless here's my code:
Required libraries
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/ScrollToPlugin.min.js"></script>
Scroll code
<script>
$(function(){
var $window = $(window)
var $scoll = $('#page-container')
var scrollTime = 0.5
var scrollDistance = 120
var scrollTop = $scoll.scrollTop()
$window.on("mousewheel DOMMouseScroll", function(event){
event.preventDefault()
var delta = event.originalEvent.wheelDelta/120 || -event.originalEvent.detail/3
scrollTop = scrollTop - parseInt(delta*scrollDistance)
scrollTop = Math.max(0, Math.min($scoll[0].scrollHeight, scrollTop))
TweenMax.to($scoll, scrollTime, {
scrollTo : { y: scrollTop, autoKill:true },
ease: Power1.easeOut,
overwrite: 5
})
})
})
</script>
Great question.
The library I use is this one:
https://github.com/cferdinandi/smooth-scroll
Simply include the smoothscroll.js file, and job done.
The mouse-wheel will now smoothly easy down the page, rather than jumping down in chunks of pixels.
It really improves the look of parallax webpages.
Btw, for parallax images, I use this library:
https://github.com/pederan/Parallax-ImageScroll
It's really easy to add to a webpage, just remember to include and initialise this library at the bottom of your webpage, after your images and HTML.
(I didn't realise that this would make a difference, but it absolutely does !)
I know I'm late to the game but I was researching the topic of smooth scrolling today after I stumbled on I Love me Wellness' site.
Analyzing the sites JavaScript I found that they are using a vanillaJS script called Luxy.js which is showcased at Luxy.js on GitHub. I find the effect rather pleasing. I don't think it's a very bad idea if implemented well. And it's very easy to implement.