Even More Syntactically Awesome Stylesheets

Reda Lemeden

Sass 3.2 has finally come out last week as a stable release, bringing in a slew of new features to help you write cleaner and more maintainable stylesheets. Here are some modern web development techniques that leverage these features.

Content blocks

Mixins can now accept blocks of content using the new @content syntax. This opens the doors to DRY up your media queries and browser hacks. What used to be:

article {
  width: 70%;

  @media screen and (min-width: 54em) {
    width: 100%;
  }
}

aside {
  width: 30%;

  @media screen and (min-width: 54em) {
    display: none;
  }
}

…can now be written as:

@mixin desktop {
    @media screen and (min-width: 54em) {
      @content;
    }
}

article {
  width: 70%;

  @include desktop {
    width: 100%;
  }
}

aside {
  width: 30%;

  @include desktop {
    display: none;
  }
}

The CSS output would remain unchanged:

article {
  width: 70%;
}

@media screen and (min-width: 54em) {
  article {
    width: 100%;
  }
}

aside {
  width: 30%;
}

@media screen and (min-width: 54em) {
  aside {
    display: none;
  }
}

With the help of a block mixin, changing the breakpoint for all the declarations is just one value away. Better yet, you can use variable breakpoints to generate content-specific media-queries:

@mixin desktop($breakpoint: 54em) {
    @media screen and (min-width: $breakpoint) {
      @content;
    }
}

header {
  height: 200px;

  @include desktop(50em) {
    height: 100px;
  }
}

// CSS Output

header {
  height: 200px;
}

@media screen and (min-width: 50em) {
  header {
    height: 100px;
  }
}

Content blocks can also be used for legacy browser styles:

@mixin ie7 {
  * + html & { // Using browser hacks
    @content;
  }
}

@mixin ie8 {
  html.ie8 & { // Using Paul Irish's conditional comments
    @content;
  }
}

aside {
  color: #000;

  @include ie7 {
    color: #555;
  }

  @include ie8 {
    color: #444;
  }
}

// CSS output

aside {
  color: #000;
}

* + html aside {
  color: #555;
}

html.ie8 aside {
  color: #444;
}

Placeholder selectors

Prior to Sass 3.2, styles meant to be extended were also compiled in the output, making extends less appealing in many situations. Enter placeholder selectors.

%banner {
  background-color: #eee;
  border: 1px solid #ddd;
  font-family: 'Helvetica', sans-serif;
}

.yellow-banner {
  @extend %banner;
  background-color: yellow;
}

.red-banner {
  @extend %banner;
  background-color: red;
}

// CSS Output

.yellow-banner, .red-banner {
  background-color: #eee;
  border: 1px solid #ddd;
  font-family: 'Helvetica', sans-serif;
}

.yellow-banner {
  background-color: yellow;
}

.red-banner {
  background-color: red;
}

Placeholder selectors do not appear in the compiled css and are simply ignored if they are not extended by any other selector.

Interpolation

Sass 3.2 makes interpolation even more useful by extending it to plain CSS directives such as @media and @keyframe. This means you can finally use variables in your keyframe definitions:

@mixin keyframes($animation-name) {
  @-webkit-keyframes $animation-name {
    @content;
  }

  @-moz-keyframes $animation-name {
    @content;
  }

  @keyframes $animation-name {
    @content;
  }
}

@include keyframes(slide-down) {
  0%, 100% { opacity: 1; }
  10%, 90% { opacity: 0; }
}

// CSS Output

@-webkit-keyframes slide-down {
  0%, 100% { opacity: 1; }
  10%, 90% { opacity: 0; }
}

@-moz-keyframes slide-down {
  0%, 100% { opacity: 1; }
  10%, 90% { opacity: 0; }
}

@keyframes slide-down {
  0%, 100% { opacity: 1; }
  10%, 90% { opacity: 0; }
}

Some of these new features, namely content blocks, may produce more code at the end of the day. That said, it’s an easy trade-off considering how easy they make it to write more organized and maintainable code.