I created a calendar slider for vue 3 that uses mousemove and touchmove events for the sliding animation as well as a function for doing some velocity animation. The project can be tested here: https://stackblitz.com/github/Der-Alex/vue-calendar-slider?file=src/components/VueCalendarSlider.vue
My first idea was to use a css custom property --posx to store the slide position with document.documentElement.style.setProperty('--posx', ${posx.value}px);. In my style part I then set transform: translate3d(var(--posx), 0, 0) to move my elements. On mouseup / touchend I then used my velocity animation, so that the slider slides a bit more based on the swipe speed.
After I got everything to work, I tested the slider in a mobile chrome browser and realized that the slider stutters really bad. After some digging and fiddling around I saw, that other sliders directly write the transform property to the element via element.style.transform = translate3d(${posx.value}px, 0, 0);, which I then also did. After that change the slider performance is much better.
To test this behaviour you can edit the following line in the src/components/VueCalendarSlider.vue file: const testCssCustomProperties = ref(false); When set to true the css custom property is written via document.documentElement.style.setProperty. When set to false, element.style.transform is used.
After the information, that style changes could be traversed down the DOM, I set the css custom property directly at the specific element that gets transformed, but the performance keeps much worse than using style.transform.
My question now is: Can anyone explain me why document.documentElement.style.setProperty('--posx', ${posx.value}px); performs so much worse than element.style.transform = translate3d(${posx.value}px, 0, 0);? I guess it has something to do with how javascript handles these parts internally and that the engine maybe moves element.style stuff to the gpu while document.documentElement.style won't be moved. But I couldn't find anything specific to that.
I hope someone can explain this to me :)
Update From 2022-09-13
I did another performance check with the Chrome devtools and measured the following:
Picture 1 shows the performance between mousedown and mouseup for the variant where I write the new clientX position directly to the element via element.style.transform:

Picture 2 shows the performance for the same events. Here I write the clientX position to the CSS custom property via element.style.setProperty('--posx', ${posx.value}px);:

So I went a bit further and changed my code so that I directly write the CSS custom property to the element via element.style.setProperty('--posx', ${posx.value}px);. Same result as in picture 2.
Testing the other way around by writing the clientX position via element.style.setProperty('transform', translate3d(${posx.value}px, 0, 0)); gives me the same result like in picture 1.
So as far as I understand, changing the CSS custom property via JavaScript forces a style recalculation for every frame, while changing the CSS property transform: translate3d doesn't.
So I guess that @S.Visser was right.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With