Custom User @mixins

Chris Coyier //

Mixins are one of the most useful and compelling reasons to use a CSS preprocessor. The typical way they are presented is for helping with CSS3 vendor prefix stuff. Indeed that is a compelling use case. No more tedious writing of all the prefixes and even more tedious updating of them over time.

However, if you are using Sass, you can use Compass, and Compass already has all those CSS3 mixins ready to go for you. Want to use the new CSS filters but want to be all future proof about it? No problem:

img {
  @include filter(grayscale(100%));
  &:hover {
    @include filter(grayscale(0));
  }
}

And you're good to go.

But handcrafted @mixins can be useful too! That is, @mixins that you author yourself to benefit your specific project. I enjoyed a post by Sacha Greif where he outlaid some @mixins he uses sometimes for specific projects.

For instance, he has some for the embossing & letterpress effects found on some sites.

@mixin box-emboss($outerOpacity, $innerOpacity) {
  box-shadow:
    rgba(white, $outerOpacity) 0 1px 0, 
    rgba(black, $innerOpacity) 0 1px 0 inset;
}

And then you could call that on any selector you wish to have that effect.

.module, header[role="banner"] {
  @include box-emboss(0.3, 0.6);
}

If you wanted to get super clever with this, you could also make a placeholder selector in which to @extend. That way you aren't repeating any code in the compiled CSS but you can separate your selectors and organize them however you want.

%box-emboss {
  @include box-emboss(0.3, 0.6);
}

header[role="banner"] {
  @extend %box-emboss;
}

...

.module {
  @extend %box-emboss;
}

Here's an example of that on CodePen:

I thought I'd share other custom @mixins I've used on some of my own projects.

Font Stacks

On this site I have four font stacks:

  1. Brand
  2. Headers
  3. Body
  4. Code

If you're properly careful with fonts, you probably aren't setting font-family too many different times in your stylesheet. If you're setting the same stack a dozen times, there is something wrong going on. But, you might have to more than once. For instance, you might have a default body font set literally on the <body>, but that won't cascade into form elements, so if you want to use the same font there you'll need to set that again on those elements. Now that you're setting it in two places, a @mixin is already useful.

I like using @mixins for this rather than a string variable set to the font families themselves, because the @mixin allows you to set other properties too if you wish. For instance, you might be using an @font-face font where you're only loading one particular weight and thus you want to set that weight whenever you set that font-family.

Here's the @mixins at the moment for this site:

@mixin font-stack-brand {
  font-family: 'Gotham Rounded A', 'Gotham Rounded B', "proxima-nova-soft", sans-serif;
}
@mixin font-stack-headers {
  font-family: 'Whitney Cond A', 'Whitney Cond B', "ronnia-condensed", sans-serif;
  font-weight: 700;
  font-style: normal;
}
@mixin font-stack-body {
  font-family: 'Whitney SSm A', 'Whitney SSm B', "ff-meta-web-pro", sans-serif;
}
@mixin font-stack-code {
  font-family: Menlo, "inconsolata", Monaco, "Courier New", Courier, monospace;
}

Media Query Mixin

You can create mixins that output the content that you pass after it in curly braces. This allows for a couple of neat possibilites. For instance, you can "name" a media query and then use it wherever you want. Meaning updating that media query only has to happen in one place. For instance:

@mixin breakpoint($point) {
  @if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @if $point == baby-bear {
    @media (max-width: 800px) { @content; }
  }
  @if $point == reverso-baby-bear {
    @media (min-width: 800px) { @content; }
  }
  @if $point == reverso-mama-bear {
    @media (min-width: 1250px) { @content; }
  }
}

And a simple usage example:

.page-wrap {
  width: 80%;
  @include breakpoint(baby-bear) {
    width: 100%;
  }
}

.footer {
  a {
    display: inline-block;
    @include breakpoint(baby-bear) {
      display: block;
    }
  }
}

You can learn more about this idea here.

Example of this on CodePen.

Animation Mixin

Compass doesn't have a @mixin for keyframe animations yet, but this is very easy to add on your own. It uses the same @content idea that the media query mixin uses above.

@mixin keyframes($name) {
  @-webkit-keyframes #{$name} {
    @content
  }
  @-moz-keyframes #{$name} {
    @content
  }
  @-ms-keyframes #{$name} {
    @content
  }
  @-o-keyframes #{$name} {
    @content
  }
  @keyframes #{$name} {
    @content
  }
}

And one to set the animation...

@mixin animation($value) {
  -webkit-animation: $value;
  -moz-animation: $value;
  -ms-animation: $value;
  -o-animation: $value;
  animation: $value;
}

Using it then becomes easy:

@include keyframes(move) {
  0%   { left: 0; }
  100% { left: 100px; }
}

.box {
  @include animation(move 0.5s ease infinite alternate);
}

You can learn more about CSS animation here.

Example of this on CodePen:

Toolbox Mixins

There are some simple helper classes that I've used on countless projects over the years. Things like an accessible hiding class and typography helping classes. If you make a mixin for these things, you can get double the bang for your buck.

// Accessible hiding
@mixin screen-reader-text() {
  position: absolute;
  top: -9999px;
  left: -9999px;
}
.screen-reader-text {
  @include screen-reader-text;
}
// Overflow Ellipsis
@mixin ellipsis() {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.ellipsis {
  @include ellipsis;
}
// Word Wrapping
@mixin word-wrap() {
  -ms-word-break: break-all;
  word-break: break-all;
  word-break: break-word;
  -webkit-hyphens: auto;
  -moz-hyphens: auto;
  hyphens: auto;
}
.word-wrap {
  @include mixin word-wrap;
}

Now you have a class name you can use in markup if you need to apply these properties. But you also have a mixin you can use to apply these properties to other declarations if you can't or don't want to touch the markup.

Note that I generally don't advise having your mixins and classes right next to each other like this. I prefer mixins to be in a separate file like _bits.scss which compiles to nothing and thus can be included on any other Sass file.

Yours?

It's always fun to share.