Skip to main content

Using the sass @for directive to generate staggered :nth-child transitions

Older browsers be damned!

Older browsers be damned!

The latest couple of Drupal websites I have worked on have been incredibly fulfilling to me as a front-end developer in that they aren't bogging themselves down with ridiculous old browser support.

We are using graceful degradation​ of course, so these browsers still have the same functionality, but don't get to have all the sexy flourishes. These are mostly done using CSS3, something that if your browser doesn't support, you probably don't deserve anyway.

So in these next few blog posts I plan to showcase some of the neat things I have come across working in this new, developer-happiness-inducing environment.

First up:

Using the sass @for directive to generate staggered :nth-child transitions

I love it when I get to use one of the sass control directives. It doesn't come up often, but when it does: oh boy. 

So in this is a fairly straightforward example let's assume we have some elements on the page that we want to fade in when we hover over the area they are contained in. 

<div class="my-container">
  <div class="my-element"></div>
  <div class="my-element"></div>
  <div class="my-element"></div>
</div>

So our sass could be something like this:

.my-element {
  @include transition(opacity 0.3s);
  @include opacity(0);
  @include inline-block;
  margin: 5px;
  width: 100px;
  height: 100px;
  background: tomato;
  .my-container:hover & {
    @include opacity(1);
  }
}

Ok, so that works, you hover over the area and they all fade in. All at once.. it looks a bit crap. A bit of a staggered effect might look cool right?

Let's not only add a transition-delay to each successive item using the :nth-child pseudo selector, let's do it the cool way - using a sass @for loop.

.my-element {
  @include transition(opacity 0.3s);
  @include opacity(0);
  @include inline-block;
  margin: 5px;
  width: 100px;
  height: 100px;
  background: tomato;

  // Loop through the items and add some delay.
  @for $i from 1 through 3 {
      &:nth-child(#{$i}) { 
       @include transition-delay(0.1s * $i); 
      }
    }

  .my-container:hover & {
    @include opacity(1);
  }
}

This loop will produce add following CSS (See the CodePen here):

.my-element:nth-child(1) {
  -moz-transition-delay: 0.1s;
  -o-transition-delay: 0.1s;
  -webkit-transition-delay: 0.1s;
  transition-delay: 0.1s;
}
.my-element:nth-child(2) {
  -moz-transition-delay: 0.2s;
  -o-transition-delay: 0.2s;
  -webkit-transition-delay: 0.2s;
  transition-delay: 0.2s;
}
.my-element:nth-child(3) {
  -moz-transition-delay: 0.3s;
  -o-transition-delay: 0.3s;
  -webkit-transition-delay: 0.3s;
  transition-delay: 0.3s;
} 

Keep in mind that this is a very simple example but you see where I am going with this. Using the @for loop means you don't have to write out the code for each :nth-child manually, and you can increase the number in the loop to allow for as many elements as you have.