title: Keyframes Parameters with SASS
body: <p>I have created a rotating carousel in CSS, which I'm pretty happy with. It's included in the snippet. The original is on <a href="https://codepen.io/CobusKruger/pen/WKzVqa" rel="nofollow noreferrer">this CodePen</a>.</p>
  
  <p>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).</p>
  
  <p>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:</p>
  
  <pre><code>$delays: 0s, -6s, -4s, -2s;
  $fullanimtime: 8s;
  $animationstops: 0%, 20%, 25%, 45%, 50%, 70%, 75%, 95%, 100%;
  </code></pre>
  
  <p>I use <code>$fullanimtime</code> as my <code>animation-duration</code>, and use the <code>$delays</code> list to configure the delays on my <code>pos-XXXX</code> styles:</p>
  
  <pre><code>.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);
  }
  </code></pre>
  
  <p>This works like a charm, and by setting up <code>$fullanimtime</code> and <code>$delays</code> correctly, I can change the animation to run correctly for any time, be it 8 seconds, or 120 seconds.</p>
  
  <p>The problem is that <code>@keyframes</code> 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.</p>
  
  <p>So the <code>$animationstops</code> variable is supposed to let me configure reasonable timing. But that doesn't work.</p>
  
  <p>For reasons I don't understand, I can't use the Sass <code>nth</code> function in a keyframe declaration, neither can I use a Sass variable.</p>
  
  <pre><code>@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 "{"
    }
  }
  </code></pre>
  
  <p>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?</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-css lang-css prettyprint-override"><code>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;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div class="frame"&gt;
    &lt;div class="box redbox pos-1"&gt;&lt;/div&gt;
    &lt;div class="box greenbox pos-2"&gt;&lt;/div&gt;
    &lt;div class="box bluebox pos-3"&gt;&lt;/div&gt;
    &lt;div class="box orangebox pos-4"&gt;&lt;/div&gt;
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>