Using Sass 3.3s @at-root for piece of mind

I often discuss on this site how I like to have ‘clarity’ or ‘cleanliness’ and order when writing my CSS/Sass. I also at some points state how the browser doesn’t give two hoots about your indentation or if you're ordering things alphabetically or not.

In thinking about keeping my code in check to keep my sanity also I’ve just recently ‘fell in love’ with the new @at-root directive coming in Sass 3.3.

With CSS3 we’ve been given some fantastic options with animations. Some developers are doing some really, really excellent work demoing these possibilities. It’s fantastic, but I have a slight problem with the syntax.

When I’m writing my Sass/CSS for to animate an element. I’ve never been a fan of having the @keyframe syntax outside of the element I want animating. Obviously this is great because of reusability of the same @keyframe ruleset but sometimes if gives me a level of abstraction I just cannot grok, and it looks messy (not that that matters).

In comes Sass 3.3s new @at-root directive

It’s the @at-root directive. It works by ‘jumping out’ of where you nest it in your Sass to be a the top level. For example you could use it simply like this:

h1 {
  font-size: 16px;
  @at-root {
    header {
      margin: 0 auto;
      width: 98%;
    }
  }
}

Which would print out the resulting CSS like this:

h1 {
  font-size: 16px;
}
header {
  margin: 0 auto;
  width: 98%;
}

One quick thing to note on this is that it prints whatever is in the @at-root after rather than before where it’s been nested.

Since seeing this it’s taken me a while to work out where I’d find a use for it. Which brings us back to animations.

So, perhaps you’re making some things on your site animate. It’d be awesome if you could include those @keyframes when you’re writing the calls to it in your CSS right? You can’t because it won’t get recognised as @keyframes need to be outside, at the root of the CSS.

At the root of the CSS

Let’s for examples sake say we want to animate the scale of an avatar when visitors hovered over it. So you would write your CSS for the .avatar, something like this.

.avatar {
  background-color: red;
  height: 120px;
  margin: 40px;
  width: 120px;
  &:hover {
    animation: sizeme .8s infinite ease-in alternate;
  }
}

For this we’d then need to make some @keyframes for sizeme so that it works. Something (ridiculous for example) like this.

@keyframes fade {
  0% { transform: scale(1.0); }
  25% { transform: scale(1.1); }
  50% { transform: scale(1.0); }
  75% { transform: scale(1.2); }
  100% { transform: scale(1.1); }
}

Ok, but how about adding that @keyframe into the SCSS rather than outside it so it’s ‘together’. Well, with Sass 3.3s new @at-root directive you can write something like this.

.avatar {
  background-color: red;
  height: 120px;
  margin: 40px;
  width: 120px;

  @at-root {
    @keyframes fade {
      0% { transform: scale(1.0); }
      25% { transform: scale(1.1); }
      50% { transform: scale(1.0); }
      75% { transform: scale(1.2); }
      100% { transform: scale(1.1); }
    }
  }
  &:hover {
    animation: fade .8s infinite ease-in alternate;
  }
}

And it would print out CSS like this

.avatar {
  background-color: red;
  height: 120px;
  margin: 40px;
  width: 120px;
}
@keyframes fade {
  0% {
    transform: scale(1);
  }
  25% {
    transform: scale(1.1);
  }
  50% {
    transform: scale(1);
  }
  75% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1.1);
  }
}
.avatar:hover {
  animation: fade .8s infinite ease-in alternate;
}

So that the animation works. You could also use the @at-root for something like @supports too.

Here's a gist of the example above on Sassmeister.

What ways can you think of that’d be a great use of the new @at-root?


So you obviously love Sass. So how about signing up to a weekly newsletter of all things Sass direct to your inbox, curated by me?