admin管理员组文章数量:1405544
I am trying to move an image slowly relative to the viewport when the user scrolls the page. Similar to the effects found here /
If the image is moved by a small value then it moves smoothly. If it is moved by a larger amount then it bees very janky.
var imageOffset = lastScrollY * 0.9;
$image.css({top: `${imageOffset}px`}); //Runs badly
var imageOffset = lastScrollY * 0.3;
$image.css({top: `${imageOffset}px`}); //Runs well
Why does the value affect the performance so much?
I have tried all the different CSS styles (transform, top, bottom, background-position). Dev tools says that I am well in the time limit for 60fps. This happens if there is nothing but the image on the page and on multiple browsers and devices. This is also not just for images but for text or anything else as well.
Bad Version: /
Good Version: /
Problem most noticeable in Firefox, in Chrome it is noticeable on first scroll and then settles down. Also most noticeable using scroll wheel or trackpad instead of dragging side scroll bar
I am trying to move an image slowly relative to the viewport when the user scrolls the page. Similar to the effects found here https://ihatetomatoes/demos/parallax-scroll-effect-part-2/
If the image is moved by a small value then it moves smoothly. If it is moved by a larger amount then it bees very janky.
var imageOffset = lastScrollY * 0.9;
$image.css({top: `${imageOffset}px`}); //Runs badly
var imageOffset = lastScrollY * 0.3;
$image.css({top: `${imageOffset}px`}); //Runs well
Why does the value affect the performance so much?
I have tried all the different CSS styles (transform, top, bottom, background-position). Dev tools says that I am well in the time limit for 60fps. This happens if there is nothing but the image on the page and on multiple browsers and devices. This is also not just for images but for text or anything else as well.
Bad Version: https://jsfiddle/4vcg8mpk/58/
Good Version: https://jsfiddle/4vcg8mpk/59/
Problem most noticeable in Firefox, in Chrome it is noticeable on first scroll and then settles down. Also most noticeable using scroll wheel or trackpad instead of dragging side scroll bar
Share Improve this question edited Sep 28, 2018 at 9:20 Duannx 8,8661 gold badge31 silver badges65 bronze badges asked Sep 19, 2018 at 23:17 Tristan WarrenTristan Warren 4351 gold badge7 silver badges17 bronze badges 17- Rendering involves layout, paint, and positing. The more of it you trigger, the more jank. csstriggers. – Jared Smith Commented Sep 19, 2018 at 23:20
- I would log out the values of imageOffset and watch how exponentially the variable increases as you scroll. – Jake Commented Sep 19, 2018 at 23:21
- 1 Can you create a minimal example with jsfiddle or the SO widget? – rafaelcastrocouto Commented Sep 19, 2018 at 23:37
- 3 Please add meaningful code here. Don't just link to a third party site — otherwise, this question will lose any value to future visitors if the site you're linking to is inaccessible. Posting a Minimal, Complete, and Verifiable example (MCVE) that demonstrates your problem would help you get better answers. For more info, see Something on my web site doesn't work. Can I just paste a link to it? Thanks! – j08691 Commented Sep 22, 2018 at 23:12
- 2 Sorry, what exactly are your fiddles supposed to show? I don’t see any image moving anywhere when scrolling the content in either one of those. – misorude Commented Sep 24, 2018 at 14:23
6 Answers
Reset to default 10 +25This is because you are trying to animate properties that impact page layout. These properties require the browser to recalculate layout of the DOM each time a layout property changes. You may not be experiencing performance lag in the second option because the layout repainted quickly, but that doesn't mean you are not going to eventually encounter performance issues while animating those properties.
I'd remend checking out this article on animation performance with CSS. It is old, but the information is still valid. I know you say that you tried animating other properties, but I would remend taking a look through all of those remendations and then implementing something that is going to be "cheap" for the browser.
You are using a scroll linked effect, which are janky in modern browsers because the scroll event lags behind what the users sees. Explained here:
Often scrolling effects are implemented by listening for the scroll event and then updating elements on the page in some way (usually the CSS position or transform property.) You can find a sampling of such effects at CSS Scroll API: Use Cases.
These effects work well in browsers where the scrolling is done synchronously on the browser's main thread. However, most browsers now support some sort of asynchronous scrolling in order to provide a consistent 60 frames per second experience to the user. In the asynchronous scrolling model, the visual scroll position is updated in the positor thread and is visible to the user before the scroll event is updated in the DOM and fired on the main thread. This means that the effects implemented will lag a little bit behind what the user sees the scroll position to be. This can cause the effect to be laggy, janky, or jittery — in short, something we want to avoid.
Source: https://developer.mozilla/en-US/docs/Mozilla/Performance/Scroll-linked_effects
You will have of course the least jankiest experience when there is less of a difference between what the user immediately sees and what is going to change after the scroll-event has executed and changed the CSS top-property.
If you multiply the top property by a number more closer to 1 (or even more) then there will be a bigger difference between what the user sees immediately and what the user sees later on (when the scroll-event has done its thing).
If you multiply the top property by a number more closer to 0 then there will be less of a difference between the immediate experience and what changes later on (when the scroll-event has done its thing).
Since there is a big difference between multiplying by 0.3 and multiplying by 0.95, the jankiness associated with asynchronous scrolling will also bee more apparent, which should answer your question:
Why does the value affect the performance so much?
The issue could be resolved with position: fixed: https://jsfiddle/4vcg8mpk/62/
// required code block
#contextImage {
position: fixed;
}
The issue is that scroll event is triggered AFTER scrolling is done, this means that scroll event is not cancelable, and also that browser might render previous DOM before JS executed...
The performance difference you mentioned is not noticeable in my environment, but according to my previous experience, browser could ignore DOM updates during scroll, if JS execution(maybe +layouting +painting) is not finished before next screen should be painted.
So browser needs to display next frame(for smooth scrolling UX) but DOM updates are not yet processed. It just uses cached version, then triggers next 'scroll' event, then trying to paint next frame, repeat...
to create smooth scrolling experience - the system must update positions of all elements in single animation frame, so it cannot do updates during 'scroll' event.
Something like this?
#contextImage {
background-image: url("https://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg");
min-height: 500px;
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="contextImage"></div>
<div id="someText">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eget turpis in nulla ultricies pretium. Nullam quis molestie velit. Vestibulum varius iaculis risus, sit amet gravida nulla efficitur quis. Sed fringilla congue nunc id tincidunt. Nam eget nunc quis est accumsan tincidunt. Aliquam maximus, nunc nec facilisis malesuada, nisi neque pulvinar magna, id hendrerit nibh nisi in justo. Morbi consequat massa massa, sed dictum mi dignissim et. Etiam id ullamcorper ante. Etiam ac magna id libero varius sollicitudin. Nulla varius blandit tristique. Mauris finibus gravida felis, at interdum eros ultricies in. Suspendisse vestibulum ornare interdum. Mauris venenatis vel nisl et efficitur. Nulla tristique nibh vel felis tincidunt egestas et eu justo.
Praesent congue ex id tempus interdum. Nunc gplacerat sollicitudin enim nec volutpat. Aenean nec dignissim turpis. Sed ut orci lobortis, consequat ante eget, posuere diam. Vestibulum ac sagittis nulla. Nam consequat ante nisl, at dapibus nibh ultrices at. Etiam ut elit feugiat, pretium augue sit amet, rutrum est. Sed et augue sit amet ligula mattis posuere. Nullam sed modo nulla.
Vestibulum hendrerit felis risus, a consectetur dui sagittis at. Morbi in accumsan dolor. Mauris sodales consectetur tortor, in maximus tellus efficitur eget. Nullam posuere hendrerit arcu, id fringilla lectus ultricies sit amet. Integer sit amet dignissim libero, modo mollis massa. Sed est nibh, mollis quis orci nec, egestas tempus leo. Etiam quis pretium mi. Donec in bibendum purus. Curabitur accumsan erat felis, ut lobortis diam luctus a. Praesent non arcu vitae tortor blandit tempus.
Praesent congue ex id tempus interdum. Nunc gplacerat sollicitudin enim nec volutpat. Aenean nec dignissim turpis. Sed ut orci lobortis, consequat ante eget, posuere diam. Vestibulum ac sagittis nulla. Nam consequat ante nisl, at dapibus nibh ultrices at. Etiam ut elit feugiat, pretium augue sit amet, rutrum est. Sed et augue sit amet ligula mattis posuere. Nullam sed modo nulla.
Vestibulum hendrerit felis risus, a consectetur dui sagittis at. Morbi in accumsan dolor. Mauris sodales consectetur tortor, in maximus tellus efficitur eget. Nullam posuere hendrerit arcu, id fringilla lectus ultricies sit amet. Integer sit amet dignissim libero, modo mollis massa. Sed est nibh, mollis quis orci nec, egestas tempus leo. Etiam quis pretium mi. Donec in bibendum purus. Curabitur accumsan erat felis, ut lobortis diam luctus a. Praesent non arcu vitae tortor blandit tempus.
Praesent congue ex id tempus interdum. Nunc gplacerat sollicitudin enim nec volutpat. Aenean nec dignissim turpis. Sed ut orci lobortis, consequat ante eget, posuere diam. Vestibulum ac sagittis nulla. Nam consequat ante nisl, at dapibus nibh ultrices at. Etiam ut elit feugiat, pretium augue sit amet, rutrum est. Sed et augue sit amet ligula mattis posuere. Nullam sed modo nulla.
Vestibulum hendrerit felis risus, a consectetur dui sagittis at. Morbi in accumsan dolor. Mauris sodales consectetur tortor, in maximus tellus efficitur eget. Nullam posuere hendrerit arcu, id fringilla lectus ultricies sit amet. Integer sit amet dignissim libero, modo mollis massa. Sed est nibh, mollis quis orci nec, egestas tempus leo. Etiam quis pretium mi. Donec in bibendum purus. Curabitur accumsan erat felis, ut lobortis diam luctus a. Praesent non arcu vitae tortor blandit tempus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ac enim vitae augue gravida pretium a et nibh. Vivamus pretium turpis quis orci venenatis efficitur. Aliquam ac pulvinar turpis, in facilisis erat. Pellentesque consectetur sodales finibus. Proin gravida, erat id pharetra condimentum, erat nisl cursus tellus, vitae viverra est orci non nunc. Nulla facilisi. Proin quis porta dolor. Suspendisse aliquam at nibh vitae pharetra. Vivamus a facilisis mi, ac faucibus nunc. Ut pharetra, diam convallis suscipit vulputate, urna quam tincidunt leo, in suscipit neque nibh vel nisl. Nullam suscipit lorem eget venenatis luctus. Sed purus dui, dignissim eget sapien quis, posuere efficitur magna. Donec quis lectus vitae erat vehicula hendrerit vel in erat.
Vestibulum sollicitudin consectetur enim. Donec lectus mi, vulputate eu tempor quis, porttitor non lacus. Nulla nisl risus, lacinia vitae magna et, hendrerit porta turpis. Sed scelerisque quam non porttitor laoreet. Sed nec ipsum metus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean accumsan bibendum rutrum. Nullam interdum elit auctor augue mattis dapibus.
</div>
</body>
</html>
In your example, the smooth of your transition is not depend on the value. Both version (big and small move) are all weird. But with the small move, it's hard to see the difference, so you may feel it smoothly. The real reason of the problem is requestAnimationFrame
.
In theory, requestAnimationFrame
is good for animation but in this case, it's bad. Let's remove the requestAnimationFrame
and use your function directly. Now it's work smoothly in both chrome and firefox and with any value. Here is the fiddle https://jsfiddle/4vcg8mpk/64/.
requestAnimationFrame
means you want to run your function in next frame
. So, when you scrolling down the body, the browser does scroll down (it makes your image go up) and excutes your function in next frame (it makes your image go down). Seem like the frame rate is not high enough so your image will up down up down. It makes your transition janky and it's easier to see with lagre move.
When remove requestAnimationFrame
your function will excute as soon as the scroll happen and run with every scroll action so it will be truly smooth.
All you have to do, is get the course. Or, you can just get the trial.
Or, just look here:
Req. HTML:
<div id="someText">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eget turpis in nulla ultricies pretium. Nullam quis molestie velit. Vestibulum varius iaculis risus, sit amet gravida nulla efficitur quis. Sed fringilla congue nunc id tincidunt. Nam eget nunc quis est accumsan tincidunt. Aliquam maximus, nunc nec facilisis malesuada, nisi neque pulvinar magna, id hendrerit nibh nisi in justo. Morbi consequat massa massa, sed dictum mi dignissim et. Etiam id ullamcorper ante. Etiam ac magna id libero varius sollicitudin. Nulla varius blandit tristique. Mauris finibus gravida felis, at interdum eros ultricies in. Suspendisse vestibulum ornare interdum. Mauris venenatis vel nisl et efficitur. Nulla tristique nibh vel felis tincidunt egestas et eu justo.
Praesent congue ex id tempus interdum. Nunc placerat sollicitudin enim nec volutpat. Aenean nec dignissim turpis. Sed ut orci lobortis, consequat ante eget, posuere diam. Vestibulum ac sagittis nulla. Nam consequat ante nisl, at dapibus nibh ultrices at. Etiam ut elit feugiat, pretium augue sit amet, rutrum est. Sed et augue sit amet ligula mattis posuere. Nullam sed modo nulla.
Vestibulum hendrerit felis risus, a consectetur dui sagittis at. Morbi in accumsan dolor. Mauris sodales consectetur tortor, in maximus tellus efficitur eget. Nullam posuere hendrerit arcu, id fringilla lectus ultricies sit amet. Integer sit amet dignissim libero, modo mollis massa. Sed est nibh, mollis quis orci nec, egestas tempus leo. Etiam quis pretium mi. Donec in bibendum purus. Curabitur accumsan erat felis, ut lobortis diam luctus a. Praesent non arcu vitae tortor blandit tempus.
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ac enim vitae augue gravida pretium a et nibh. Vivamus pretium turpis quis orci venenatis efficitur. Aliquam ac pulvinar turpis, in facilisis erat. Pellentesque consectetur sodales finibus. Proin gravida, erat id pharetra condimentum, erat nisl cursus tellus, vitae viverra est orci non nunc. Nulla facilisi. Proin quis porta dolor. Suspendisse aliquam at nibh vitae pharetra. Vivamus a facilisis mi, ac faucibus nunc. Ut pharetra, diam convallis suscipit vulputate, urna quam tincidunt leo, in suscipit neque nibh vel nisl. Nullam suscipit lorem eget venenatis luctus. Sed purus dui, dignissim eget sapien quis, posuere efficitur magna. Donec quis lectus vitae erat vehicula hendrerit vel in erat.
Vestibulum sollicitudin consectetur enim. Donec lectus mi, vulputate eu tempor quis, porttitor non lacus. Nulla nisl risus, lacinia vitae magna et, hendrerit porta turpis. Sed scelerisque quam non porttitor laoreet. Sed nec ipsum metus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean accumsan bibendum rutrum. Nullam interdum elit auctor augue mattis dapibus.
</div>
<div id="contextImage">
</div>
Req. CSS:
someText {
height: 300vh;
width: 200px;
position: absolute;
}
contextImage {
will-change: top;
transform: translateZ(0);
position: fixed;
height: 80vh;
width: 100%;
background-image: url(https://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg);
background-size: cover;
}
Req. JavaScript & JQuery:
var $window = $(window);
var windowHeight = $window.height();
var $exampleDiv = $('#someText');
var $contextImage = $('#contextImage');
//Variables for debouncing scroll
var lastScrollY = window.pageYOffset;
var ticking = false;
//Debouncing scroll events
window.addEventListener('scroll', getYOffset, false);
//Keeps track of last sccroll event
function getYOffset() {
lastScrollY = window.pageYOffset;
requestTick();
}
//stops further rAFs until current is plete
function requestTick() {
if (!ticking) {
requestAnimationFrame(parallax);
ticking = false;
}
}
//When new animation frame availible then do animation
function parallax() {
if (lastScrollY < (4 * windowHeight)) {
var imageOffset = (-lastScrollY * 0.1);
$contextImage.css({transform: `translateY(${imageOffset}px)`});
}
// Allow new rAFs
ticking = false;
}
There you go. Problem solved.
Hope this helps!!!
版权声明:本文标题:javascript - Why will changing this CSS effect using JS only work smoothly for certain values? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744290904a2599108.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论