7

I'm doing an animation with CSS variables, where a CSS variable value changes based on the page scroll. That variable is then used on animation with keyframes.

Originally it's updating correctly only on Firefox. Meanwhile, I found a way to make it work on Chrome too, by forcing a repaint, in this case, animate the color from #000 to #001.

/* --scale is dynamic changed by JS */

@keyframes move {
    0% {
        transform: translateX(0) scale(var(--scale));
        color: #000;
    }
    100% {
        transform: translateX(33vw) scale(1.5);
        color: #001;
    }
}

You can see a demo at codepen

6
  • Any updates on this issue? Commented Apr 29, 2020 at 13:08
  • @DimitarSpassov, my workaround was to create 2 animations: The original one a an moveExpensive where I used left instead of translateX, forcing the repaint. Then with JS detect the browser. If it's FF use move, otherwise use moveExpensive. Commented Apr 29, 2020 at 13:23
  • Maybe I'm doing something wrong, but on Safari the issue remains, even if I replace the translateX transformation with left. Commented Apr 29, 2020 at 13:40
  • Oh sorry, @DimitarSpassov, forgot to mention, I didn't use variables on the fallback version. In my case, I used hardcoded values (%) and did some other workarounds. In summary: I didn't find a way to make it work with CSS variables. Commented Apr 29, 2020 at 17:58
  • Oh, alright. Thanks for the update. Commented Apr 29, 2020 at 19:44

3 Answers 3

6

I also ran into this issue and solved it by setting the element.style.animation attribute in JavaScript after calling setProperty(). It seems like @keyframes doesn't update after setting the animation in CSS.

Sign up to request clarification or add additional context in comments.

Comments

3

This is a WebKit bug. I discovered this issue today by reading Safari Technology Preview 149 changelog, which means it should be fixed in Safari 16, to be released later this year.

Added support for custom properties in @keyframes rules (251733@main)

Comments

0

An alternative for those (like myself) who are using Styled Component's keyframes`` function, you can exchange the css variable for a prop by defining a function much like the following:

import styled, { Keyframes, keyframes } from 'styled-components';

const move = (scale: number): Keyframes => keyframes`
  0% {
      transform: translateX(0) scale(${scale});
      color: #000;
  }
  100% {
      transform: translateX(33vw) scale(1.5);
      color: #001;
  }
`

const AnimatedElement = styled.div<{ scale: number }>`
  animation: ${(props) => move(props.scale)} 2s linear infinite;
`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.