Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keyframes Parameters with SASS

I have created a rotating carousel in CSS, which I'm pretty happy with. It's included in the snippet. The original is on this CodePen.

It basically rotates the positions of four boxes. The total animation time is 8 seconds and I've set it up so it remains static for 20% of that, then moves the boxes for 5% and then waits again (run the snippet; I don't think I've explained it very well).

Now I want to parameterise it. Sass is my weapon of choice, and I can easily set up a few variables that would help. So right at the top of my styles, I have this:

$delays: 0s, -6s, -4s, -2s;
$fullanimtime: 8s;
$animationstops: 0%, 20%, 25%, 45%, 50%, 70%, 75%, 95%, 100%;

I use $fullanimtime as my animation-duration, and use the $delays list to configure the delays on my pos-XXXX styles:

.pos-1 {
  animation-delay: nth($delays, 1);
}
.pos-2 {
  animation-delay: nth($delays, 2);
}
.pos-3 {
  animation-delay: nth($delays, 3);
}
.pos-4 {
  animation-delay: nth($delays, 4);
}

This works like a charm, and by setting up $fullanimtime and $delays correctly, I can change the animation to run correctly for any time, be it 8 seconds, or 120 seconds.

The problem is that @keyframes use percentages. So if I set the other variables for a long animation time, the actual transitions that move the boxes get real slow: For 8 seconds, the transition runs for 400 ms, but for 120 seconds, they take 6 seconds, which is more annoying than cool.

So the $animationstops variable is supposed to let me configure reasonable timing. But that doesn't work.

For reasons I don't understand, I can't use the Sass nth function in a keyframe declaration, neither can I use a Sass variable.

@keyframes rotate-board {
  nth($animationstops, 1) {
    // This gives an error:
    // Invalid CSS after "nth": expected keyframes selector, was "($animationstop..."
  }
  $somevariable {
    // This gives an error:
    // Invalid CSS after " $somevalue ": expected ":", was "{"
  }
}

Is there a way around this, or have I found a limitation of Sass? And is there another pre-processor that I should use instead if I want to do this?

body {
  margin: 0;
  padding: 0;
}
.frame {
  height: 580px;
  width: 100vw;
  background: lightgrey;
  position: relative;
  box-sizing: border-box;
}

.box {
  width: calc(50% - 30px);
  height: calc(50% - 30px);
  top: 20px;
  left: 20px;
  position: absolute;
  animation-name: rotate-board;
  animation-duration: 8s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

.redbox {
  background: red;
}
.greenbox {
  background: green;
}
.bluebox {
  background: blue;
}
.orangebox {
  background: orange;
}

@keyframes rotate-board {
  0% {
    top: 20px;
    left: 20px;
    bottom: calc(50% + 10px);
    right: calc(50% + 10px);
  }
  20% {
    top: 20px;
    left: 20px;
    bottom: calc(50% + 10px);
    right: calc(50% + 10px);
  }
  25% {
    top: 20px;
    left: calc(50% + 10px);
    bottom: calc(50% + 10px);
    right: 20px;
  }
  45% {
    top: 20px;
    left: calc(50% + 10px);
    bottom: calc(50% + 10px);
    right: 20px;
  }
  50% {
    top: calc(50% + 10px);
    left: calc(50% + 10px);
    bottom: 20px;
    right: 20px;
  }
  70% {
    top: calc(50% + 10px);
    left: calc(50% + 10px);
    bottom: 20px;
    right: 20px;
  }
  75% {
    top: calc(50% + 10px);
    left: 20px;
    bottom: 20px;
    right: calc(50% + 10px);
  }
  95% {
    top: calc(50% + 10px);
    left: 20px;
    bottom: 20px;
    right: calc(50% + 10px);
  }
  100% {
    top: 20px;
    left: 20px;
    bottom: calc(50% + 10px);
    right: calc(50% + 10px);
  }
}

.pos-1 {
  animation-delay: 0s;
}
.pos-2 {
  animation-delay: -6s;
}
.pos-3 {
  animation-delay: -4s;
}
.pos-4 {
  animation-delay: -2s;
}
<div class="frame">
  <div class="box redbox pos-1"></div>
  <div class="box greenbox pos-2"></div>
  <div class="box bluebox pos-3"></div>
  <div class="box orangebox pos-4"></div>
</div>
like image 595
Cobus Kruger Avatar asked Dec 12 '25 17:12

Cobus Kruger


1 Answers

You could write your variables like this:

#{nth($animationstops, 1)} 

I created a Sassmeister for you: https://www.sassmeister.com/gist/7c9b06c6b5a7cc580b14cbd1b312c566

Here it is at work: https://codepen.io/anon/pen/PBeNLV

PS: Your animation is very beautiful! Congrats! :)

like image 138
ReSedano Avatar answered Dec 15 '25 08:12

ReSedano