Question

I'm trying to create an animating loading spinner in CSS using LESS and I'd like to be able to dynamically set the color of the spinner by setting a class to the element displaying the spinner. I'm using Web Essentials 2012 for Visual Studio 2012 for the creation and compilation of LESS files.

I'm new to LESS and can't seem to find a way to add dynamic keyframe names. Consider the following code:

LESS:

@white: #FFF;

.Spin(@color)
{
    0%, 100%
    {
        box-shadow: 0em -3em 0em 0.2em @color, 2em -2em 0 0em @color, 3em 0em 0 -0.5em @color, 2em 2em 0 -0.5em @color, 0em 3em 0 -0.5em @color, -2em 2em 0 -0.5em @color, -3em 0em 0 -0.5em @color, -2em -2em 0 0em @color;
    }

    12.5%
    {
        box-shadow: 0em -3em 0em 0em @color, 2em -2em 0 0.2em @color, 3em 0em 0 0em @color, 2em 2em 0 -0.5em @color, 0em 3em 0 -0.5em @color, -2em 2em 0 -0.5em @color, -3em 0em 0 -0.5em @color, -2em -2em 0 -0.5em @color;
    }

    25%
    {
        box-shadow: 0em -3em 0em -0.5em @color, 2em -2em 0 0em @color, 3em 0em 0 0.2em @color, 2em 2em 0 0em @color, 0em 3em 0 -0.5em @color, -2em 2em 0 -0.5em @color, -3em 0em 0 -0.5em @color, -2em -2em 0 -0.5em @color;
    }

    37.5%
    {
        box-shadow: 0em -3em 0em -0.5em @color, 2em -2em 0 -0.5em @color, 3em 0em 0 0em @color, 2em 2em 0 0.2em @color, 0em 3em 0 0em @color, -2em 2em 0 -0.5em @color, -3em 0em 0 -0.5em @color, -2em -2em 0 -0.5em @color;
    }

    50%
    {
        box-shadow: 0em -3em 0em -0.5em @color, 2em -2em 0 -0.5em @color, 3em 0em 0 -0.5em @color, 2em 2em 0 0em @color, 0em 3em 0 0.2em @color, -2em 2em 0 0em @color, -3em 0em 0 -0.5em @color, -2em -2em 0 -0.5em @color;
    }

    62.5%
    {
        box-shadow: 0em -3em 0em -0.5em @color, 2em -2em 0 -0.5em @color, 3em 0em 0 -0.5em @color, 2em 2em 0 -0.5em @color, 0em 3em 0 0em @color, -2em 2em 0 0.2em @color, -3em 0em 0 0em @color, -2em -2em 0 -0.5em @color;
    }

    75%
    {
        box-shadow: 0em -3em 0em -0.5em @color, 2em -2em 0 -0.5em @color, 3em 0em 0 -0.5em @color, 2em 2em 0 -0.5em @color, 0em 3em 0 -0.5em @color, -2em 2em 0 0em @color, -3em 0em 0 0.2em @color, -2em -2em 0 0em @color;
    }

    87.5%
    {
        box-shadow: 0em -3em 0em 0em @color, 2em -2em 0 -0.5em @color, 3em 0em 0 -0.5em @color, 2em 2em 0 -0.5em @color, 0em 3em 0 -0.5em @color, -2em 2em 0 0em @color, -3em 0em 0 0em @color, -2em -2em 0 0.2em @color;
    }
}

.Keyframes(@name, @color)
{
    @-webkit-keyframes @name { .Spin(@color); }
    @-moz-keyframes @name { .Spin(@color); }
    @-ms-keyframes @name { .Spin(@color); }
    @-o-keyframes @name { .Spin(@color); }
    @keyframes @name { .Spin(@color); }
}

.Animate(@name, @color)
{
    .Keyframes(@name, @color);
    animation: 1.3s linear 0s normal none infinite @name;
    -moz-animation: 1.3s linear 0s normal none infinite @name;
    -o-animation: 1.3s linear 0s normal none infinite @name;
    -webkit-animation: 1.3s linear 0s normal none infinite @name;
}

.loading
{
    display: inline-block;
    padding-left: 2.5em;
    position: relative;
    -webkit-backface-visibility: hidden;
    cursor: default !important;

    &:before
    {
        border-radius: 50%;
        content: "";
        font-size: 0.2em;
        height: 1em;
        left: 0;
        margin: 5em auto 5em 5em;
        position: absolute;
        top: 0;
        width: 1em;
    }

    &.white:before
    {
        .Animate(spinwhite, @white);
    }
}

This compiles to the following code:

CSS (I left out all vendor specific keyframe notations for readability):

.loading {
  display: inline-block;
  padding-left: 2.5em;
  position: relative;
  -webkit-backface-visibility: hidden;
  cursor: default !important;
}
.loading:before {
  border-radius: 50%;
  content: "";
  font-size: 0.2em;
  height: 1em;
  left: 0;
  margin: 5em auto 5em 5em;
  position: absolute;
  top: 0;
  width: 1em;
}
.loading.white:before {
  animation: 1.3s linear 0s normal none infinite spinwhite;
  -moz-animation: 1.3s linear 0s normal none infinite spinwhite;
  -o-animation: 1.3s linear 0s normal none infinite spinwhite;
  -webkit-animation: 1.3s linear 0s normal none infinite spinwhite;
}
@keyframes @name {
  0%,
  100% {
    box-shadow: 0em -3em 0em 0.2em #ffffff, 2em -2em 0 0em #ffffff, 3em 0em 0 -0.5em #ffffff, 2em 2em 0 -0.5em #ffffff, 0em 3em 0 -0.5em #ffffff, -2em 2em 0 -0.5em #ffffff, -3em 0em 0 -0.5em #ffffff, -2em -2em 0 0em #ffffff;
  }
  12.5% {
    box-shadow: 0em -3em 0em 0em #ffffff, 2em -2em 0 0.2em #ffffff, 3em 0em 0 0em #ffffff, 2em 2em 0 -0.5em #ffffff, 0em 3em 0 -0.5em #ffffff, -2em 2em 0 -0.5em #ffffff, -3em 0em 0 -0.5em #ffffff, -2em -2em 0 -0.5em #ffffff;
  }
  25% {
    box-shadow: 0em -3em 0em -0.5em #ffffff, 2em -2em 0 0em #ffffff, 3em 0em 0 0.2em #ffffff, 2em 2em 0 0em #ffffff, 0em 3em 0 -0.5em #ffffff, -2em 2em 0 -0.5em #ffffff, -3em 0em 0 -0.5em #ffffff, -2em -2em 0 -0.5em #ffffff;
  }
  37.5% {
    box-shadow: 0em -3em 0em -0.5em #ffffff, 2em -2em 0 -0.5em #ffffff, 3em 0em 0 0em #ffffff, 2em 2em 0 0.2em #ffffff, 0em 3em 0 0em #ffffff, -2em 2em 0 -0.5em #ffffff, -3em 0em 0 -0.5em #ffffff, -2em -2em 0 -0.5em #ffffff;
  }
  50% {
    box-shadow: 0em -3em 0em -0.5em #ffffff, 2em -2em 0 -0.5em #ffffff, 3em 0em 0 -0.5em #ffffff, 2em 2em 0 0em #ffffff, 0em 3em 0 0.2em #ffffff, -2em 2em 0 0em #ffffff, -3em 0em 0 -0.5em #ffffff, -2em -2em 0 -0.5em #ffffff;
  }
  62.5% {
    box-shadow: 0em -3em 0em -0.5em #ffffff, 2em -2em 0 -0.5em #ffffff, 3em 0em 0 -0.5em #ffffff, 2em 2em 0 -0.5em #ffffff, 0em 3em 0 0em #ffffff, -2em 2em 0 0.2em #ffffff, -3em 0em 0 0em #ffffff, -2em -2em 0 -0.5em #ffffff;
  }
  75% {
    box-shadow: 0em -3em 0em -0.5em #ffffff, 2em -2em 0 -0.5em #ffffff, 3em 0em 0 -0.5em #ffffff, 2em 2em 0 -0.5em #ffffff, 0em 3em 0 -0.5em #ffffff, -2em 2em 0 0em #ffffff, -3em 0em 0 0.2em #ffffff, -2em -2em 0 0em #ffffff;
  }
  87.5% {
    box-shadow: 0em -3em 0em 0em #ffffff, 2em -2em 0 -0.5em #ffffff, 3em 0em 0 -0.5em #ffffff, 2em 2em 0 -0.5em #ffffff, 0em 3em 0 -0.5em #ffffff, -2em 2em 0 0em #ffffff, -3em 0em 0 0em #ffffff, -2em -2em 0 0.2em #ffffff;
  }
}

Note how the keyframes name is @name instead of spinwhite what I'd like it to be. According to this SO post, this approach should be working in LESS 1.7.x and up, but according to the changelog of Web Essentials, the compiler used in the latest version is version 1.6.3.

Does anyone have an idea of how to get this working? Or is it just gonna be a matter of waiting and be patient and hoping Web Essentials will be updating its compiler?

Was it helpful?

Solution

Found a working solution, but it feels a bit like a "hack". I've downloaded the latest LESS-compiler and overwritten the one used by Web Essentials, which is found at C:\Users[USER]\AppData\Local\Microsoft\VisualStudio\11.0\Extensions\[SOME SEEMINGLY RANDOM CHARACTERS]\Resources\Scripts with filename less-1.6.3.min.js.

For the new compiler to work I did have to use the same filename as the existing compiler. After that it was just a matter of restarting Visual Studio and resaving my LESS-file. The generated CSS-file now contains the code I'd expected and wanted.

Until Web Essentials is updated with the new LESS compiler, this solution will suffice for me.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top