0

On a recent project, I took Dave Rupert's Cheapass Parallax idea (Demo) and ran with it. I have several chucks of svg shapes (23 relatively simple shapes, all inline svg) down the right side of the page which all scroll at different speeds, creating a cool effect.

The basic idea of Dave's idea was to have a single css variable that you change on scroll, which the element uses in a calc() statement to change its transform property, moving up and down the page, creating the parallax effect.

Here's his snippet:

const title = document.querySelector('h1.title');
const speed = 0.2;
title.style.transform = 'translateY( calc( var(--scrollparallax) * 1px ) )';

window.addEventListener('scroll', function() {
  title.style.setProperty("--scrollparallax", (document.body.scrollTop || document.documentElement.scrollTop) * speed);
});

I basically did this same thing but put a few different speed variables and the transform calc statement in my scss file. I also had to set different 'scrollparallax' vars for each little chunk, since their distance from the top of the page affects how that would work.

*SCSS*

$speed1: 0.15px;
$speed2: 0.1px;
$speed3: 0.05px;
$speed4: 0.2px;

.firstSvgShape {
  transform: translateY( calc( var(--dist) * #{$speed1}) );
}
.secondSvgShape {
  transform: translateY( calc( var(--dist) * #{$speed3}) );
}

(etc...)

*JS*
const hexGroup1 = document.querySelector('.hex-group-1');
const hexGroup2 = document.querySelector('.hex-group-2');
const hexGroup3 = document.querySelector('.hex-group-3');

window.addEventListener('scroll', () => {

  const top = document.body.scrollTop || document.documentElement.scrollTop;

  if (hexGroup1) {
    hexGroup1.style.setProperty("--dist", hexGroup1.offsetTop - top);
  }

  if (hexGroup2) {
    hexGroup2.style.setProperty("--dist", hexGroup2.offsetTop - top);
  }

  if (hexGroup3) {
    hexGroup3.style.setProperty("--dist", hexGroup3.offsetTop - top);
  }

});

Originally, I had actually done everything in js, and had different css vars on each individual svg element that all changed as the page scrolled. I noticed some lagging on the page (on my refurbished 13" 2015 macbook pro on a 27" 4k monitor), but it wasn't significant.

I refactored the thing to only change 4 css variables in one scroll event function, and everything else in css, which I thought would give me a decent performance boost, but it's basically the exact same. Scrolling just isn't as silky smooth as the other pages on the same site.

Is there anything I can do to get the scrolling with this effect nice and smooth? Ditch the css vars and try something else? Break the inline svgs out and use img tags?

willfalcon
  • 1
  • 1
  • 5
  • It would be helpful to see *your* code, since that's the code that's slow. – Pointy Aug 22 '18 at 15:02
  • Sure, I'll add that in the question. – willfalcon Aug 22 '18 at 15:04
  • Actually, the expensive code is right there. You modify the DOM at a `scroll` event, which is firing at high rate. See [this](https://developer.mozilla.org/en-US/docs/Web/Events/scroll#Example) code example for throttlling. – ccprog Aug 22 '18 at 15:09
  • I figured the main problem would be in the scroll event... Just not sure how to make it work without it, you know? Can't use a debouncer/setTimeout/anything like that since the whole point is for it to change immediately & smoothly with the scroll. – willfalcon Aug 22 '18 at 15:13
  • @WillHawks check that link in the previous comment. That uses `.requestAnimationFrame()` in concert with the "scroll" handler. Browsers fire "scroll" very aggressively. – Pointy Aug 22 '18 at 15:15
  • So I've adjusted the code to use requestAnimationFrame as per that example.. just put all the ".setProperty"s in a function and toggle that ticking var, calling the function if it's false. I don't see any real visible improvement.. still works about the same. But it's background perf boost hopefully. – willfalcon Aug 22 '18 at 15:27
  • 1
    I found this because I had the same problem with performance. In my case it was because I set the variable on the html element. Changing it so that I only set it on the element that needed it drastically increased performance. I guess when you set it on html/:root the browser needs to redraw the entire page perhaps? – powerbuoy Oct 05 '20 at 18:34
  • In my case, adding `will-change: ` to the element drastically improved performance. – xsonic Aug 03 '22 at 14:23

0 Answers0