Handy Sass Mixins

Mixins are one of the most powerful features of Sass. Mixins allow for efficient and clean code repetitions as well as an easy way to adjust your code with ease. If you are using Sass in your development workflow, no doubt you are using some of the mixins that I have covered below but some might also be new and helpful.

I have also added the mixins to GitHub. If you have any favourite mixins, thoughts, tweaks or modifications, be sure to submit a pull request or add them in the comments below.

GitHub

If you are new to Sass, I would highly recommend you check out my Why you scared of Sass? post first.


Responsive Breakpoints

My most utilised mixin that I don’t think I could live without anymore. Just set your breakpoint at whatever width you desire and go crazy.


@mixin breakpoint($point) {
  @if $point == large {
    @media (min-width: 64.375em) { @content; }
  }
  @else if $point == medium {
    @media (min-width: 50em) { @content; }
  }
  @else if $point == small {
    @media (min-width: 37.5em)  { @content; }
  }
}

Usage:


.page-wrap {
  width: 75%;
  @include breakpoint(large) { width: 60%; }
  @include breakpoint(medium) { width: 80%; }
  @include breakpoint(small) { width: 95%; }
}

Output:


.page-wrap {
  width: 75%;
}
@media (min-width: 64.375em) {
  .page-wrap {
    width: 60%;
  }
}
@media (min-width: 50em) {
  .page-wrap {
    width: 80%;
  }
}
@media (min-width: 37.5em) {
  .page-wrap {
    width: 95%;
  }
}

Retina Images

This mixin by Jason Zimdars is a breeze to use and offers a greater visual experience to those that are lucky enough to have a retina device.


@mixin image-2x($image, $width, $height) {
  @media (min--moz-device-pixel-ratio: 1.3),
         (-o-min-device-pixel-ratio: 2.6/2),
         (-webkit-min-device-pixel-ratio: 1.3),
         (min-device-pixel-ratio: 1.3),
         (min-resolution: 1.3dppx) {
    /* on retina, use image that's scaled by 2 */
    background-image: url($image);
    background-size: $width $height;
  }
}

Usage:


div.logo {
   background: url("logo.png") no-repeat;
   @include image-2x("logo2x.png", 100px, 25px);
 }

Output:


div.logo {
  background: url("logo.png") no-repeat;
}
@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) {
  div.logo {
    /* on retina, use image that's scaled by 2 */
    background-image: url("logo2x.png");
    background-size: 100px 25px;
  }
}

Clearfix

There are a few ways to implement the clearfix hack but the following Sass Mixin has been in my toolbox for the last year thanks to this article on Nicolas Gallagher’s blog.


@mixin clearfix() {
    &:before,
    &:after {
        content: "";
        display: table;
    }
    &:after {
        clear: both;
    }
}

Usage:


.article {
     @include clearfix();
}

Output:


.article {
  *zoom: 1;
}
.article:before, .article:after {
  content: "";
  display: table;
}
.article:after {
  clear: both;
}

Box Sizing

Reset your elements box model with ease.


@mixin box-sizing($box-model) {
  -webkit-box-sizing: $box-model; // Safari <= 5
     -moz-box-sizing: $box-model; // Firefox <= 19
          box-sizing: $box-model;
}

Usage:


*,
*:after,
*:before {
  @include box-sizing(border-box);
}

Output:


*,
*:after,
*:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

Border Radius

Always a handy mixin. Set every border radius or just a single side without worrying about all those prefixes.


@mixin border-radius($radius) {
  -webkit-border-radius: $radius;
  border-radius: $radius;
  background-clip: padding-box;  /* stops bg color from leaking outside the border: */
}

// Single side border-radius

@mixin border-top-radius($radius) {
  -webkit-border-top-right-radius: $radius;
  border-top-right-radius: $radius;
   -webkit-border-top-left-radius: $radius;
   border-top-left-radius: $radius;
   background-clip: padding-box;
}
@mixin border-right-radius($radius) {
  -webkit-border-bottom-right-radius: $radius;
  border-bottom-right-radius: $radius;
     -webkit-border-top-right-radius: $radius;
     border-top-right-radius: $radius;
     background-clip: padding-box;
}
@mixin border-bottom-radius($radius) {
  -webkit-border-bottom-right-radius: $radius;
  border-bottom-right-radius: $radius;
   -webkit-border-bottom-left-radius: $radius;
   border-bottom-left-radius: $radius;
   background-clip: padding-box;
}
@mixin border-left-radius($radius) {
  -webkit-border-bottom-left-radius: $radius;
  border-bottom-left-radius: $radius;
     -webkit-border-top-left-radius: $radius;
     border-top-left-radius: $radius;
     background-clip: padding-box;
}

Usage:


.button {
  @include border-radius(5px);
}

.submit-button {
  @include border-top-radius(10px);
  @include border-right-radius(8px);
  @include border-bottom-radius(10px);
  @include border-left-radius (6px);
}

Output:


.button {
  -webkit-border-radius: 5px;
  border-radius: 5px;
  background-clip: padding-box;
  /* stops bg color from leaking outside the border: */
}

.submit-button {
  -webkit-border-top-right-radius: 10px;
  border-top-right-radius: 10px;
  -webkit-border-top-left-radius: 10px;
  border-top-left-radius: 10px;
  background-clip: padding-box;
}

Opacity

Set the opacity for all browsers and provide a filter fallback for IE8.


@mixin opacity($opacity) {
  opacity: $opacity;
  $opacity-ie: $opacity * 100;
  filter: alpha(opacity=$opacity-ie); //IE8
}

Usage:


.article-heading {
  @include opacity(0.8);
}

Output:


.article-heading {
  opacity: 0.8;
  filter: alpha(opacity=0.8);
}

Center-align a block level element

Quickly center any element within its parent. Requires width or max-width to be set.


@mixin center-block {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

Usage:


.footer-wrap {
  width: 450px;
  @include center-block;
}

Output:


.footer-wrap {
  width: 450px;
  display: block;
  margin-left: auto;
  margin-right: auto;
}

Text Overflow

An easy way to truncate text with an ellipsis. Requires the element to be block or inline-block.


@mixin text-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

Usage:


.text-truncate {
  @include text-truncate;
}

Output:


.text-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

Absolute Positioned

Pass in the desired location of your target element to produce all the necessary positioning code.


@mixin abs-pos ($top: auto, $right: auto, $bottom: auto, $left: auto) {
  top: $top;
  right: $right;
  bottom: $bottom;
  left: $left;
  position: absolute;
}

Usage:


.abs {
  @include abs-pos(10px, 10px, 5px, 15px);
}

Output:


.abs {
  top: 10px;
  right: 10px;
  bottom: 5px;
  left: 15px;
  position: absolute;
}

Font Size

This mixin sets the font size in rem's with a px fallback.


@mixin font-size($sizeValue: 12 ){
  font-size: $sizeValue + px; //fallback for old browsers
  font-size: (0.125 * $sizeValue) + rem;
}

Usage:


body {
  @include font-size(16);
}

Output:


body {
  font-size: 16px;
  font-size: 2rem;
}

Line Height

This mixin sets the line height in rem's with a px fallback.


@mixin line-height($heightValue: 12 ){
	line-height: $heightValue + px; //fallback for old browsers
	line-height: (0.125 * $heightValue) + rem;
}

Usage:


body {
  @include line-height (16);
}

Output:


body {
  line-height: 16px;
  line-height: 2rem;
}

Happy Coding!

40 Comments

  1. I don’t think that `clearfix`, `center-block`, and `text-truncate` need to be mixins. They would be better off used as placeholders (see here: http://sass-lang.com/docs/yardoc/file.SASS_CHANGELOG.html#placeholder_selectors_).

    The main benefit here is that you won’t have the contents of what you’re trying to include repeated in your compiled CSS but instead, where you defined `%clearfix` you’ll get a list of all the selectors that called the `@extend`.

    For example, using `text-truncate`

    
    %text-truncate {
     overflow: hidden;
     text-overflow: ellipsis;
     white-space: nowrap;
    }

    Usage:

    
    .text-truncate-1 {
      @extend text-truncate;
    }
    .text-truncate-2 {
      @extend text-truncate;
    }

    Output:

    
    .text-truncate-1, .text-truncate-2 {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    • Remy you have a very valid point…. Time for some investigating.

    • my text-truncate looks like this.

      
      %concatenated
          text-overflow: ellipsis
          vertical-align: top
          white-space: nowrap
          overflow: hidden
          display: inline-block

      that way it works for elements that don’t have a block model (if you are truncating it seems like a pretty safe guess that it will be inline) and the vertical align top is a fix for mozilla FF.

    • I agree, I think in general you should be trying to @extend rather than @include as this reuses blocks of code rather than appending the same code to different elements

    • The only downside to %placeholders is that you can’t extend upon them inside media-queries. I’d love to use them, but without a valid way to extend upon them, especially for mobile-first, you’ll have to be really careful where you use them.

    • Well done Remy… Placeholder is the DRY way to go there.

    • For clarity, I believe that should be @extend %text-truncate;. Great tip though!

  2. Be careful when using the retina image one – it will probably generate a lot of repeats of the media query that you might not expect.

  3. I see a couple mixins like clearfix and border box with before and after pseudo-elements. Why is that?

  4. Wouldn’t the rem and line-height mixin math depend on what you set your base html font-size to be?

    • Yeah, I was thinking this too. This would make more sense:

      
      @mixin font-size($size: 12, $base: 16) {
        font-size: $size; // fallback for old browsers
        font-size: ($size / $base) * 1rem;
      }
    • Very cool Jemma, did you leave out + px tho?

      
      @mixin font-size($size: 12, $base: 16) {
          font-size: $size + px;
          font-size: ($size / $base) * 1rem;
      }
  5. Cool thanks for sharing! A mini-grid mixin would be cool.

    • A friend of mine made this one if you’re interested.

  6. Wouldn’t compass give you a majority of these mixins

  7. Good compilation. At thoughtbot we use bourbon.io and neat.bourbon.io to make it easier to maintain and use these mixins across projects.

    • Cheers Reda. They look like pretty awesome resources!

  8. CSS output for opacity filter should be like this:
    filter: alpha(opacity=80);

    Currently you have 0.8 there.

    You do 0.8*100 inside the mixin.

  9. You don’t need to set a width and height of image in retina mixin, because sass has function called image-width() which will give you size and all you must do is to divide it by 2 ;)

    • I think this function is only exists in Compass, not in SASS

  10. Great list of mixins, Thanks.

    A couple of notes:

    1. The problem I’ve experienced (and I’ve seen many others too) with Responsive Breakpoints is that the output CSS is a unbelievable repetition of the same media query per selector instead of creating a single media query per break point, which in my eyes it completely defeats the purpose of the Responsive Breakpoints.

    So if you have this:

    
    .page-wrap {
      width: 75%;
      @include breakpoint(large) { width: 60%; }
      @include breakpoint(medium) { width: 80%; }
      @include breakpoint(small) { width: 95%; }
    }
    
    .header-container {
      width: 1%;
      @include breakpoint(large) { width: 2%; }
      @include breakpoint(medium) { width: 3%; }
      @include breakpoint(small) { width: 4%; }
    }

    You end up with this:

    
    .page-wrap {
      width: 75%;
    }
    @media (min-width: 64.375em) {
      .page-wrap {
        width: 60%;
      }
    }
    @media (min-width: 50em) {
      .page-wrap {
        width: 80%;
      }
    }
    @media (min-width: 37.5em) {
      .page-wrap {
        width: 95%;
      }
    }
    
    .header-container  {
      width: 1%;
    }
    @media (min-width: 64.375em) {
      .header-container {
        width: 2%;
      }
    }
    @media (min-width: 50em) {
      .header-container {
        width: 3%;
      }
    }
    @media (min-width: 37.5em) {
      .header-container {
        width: 4%;
      }
    }

    And 2. Line height is a unit-less property, no need to add px or rem.

    Thanks.

    • I think you are wrong!
      Line-height can be unitless, but also can be used with units.

      The responsive breakpoints mixin generates more css code, but much easier to maintain the scss file.
      You don’t have to rebuild the selectors in each media query and this is a big advantage I think.

  11. Hi Jake,

    First off, thank you very much! I find this really useful as I’m pretty new to SASS, can I request for more of this? Like box shadows and animations would be awesome. Awesome work you have here. I hope to see more.

    • Hi Rod,

      Cheers. I also find it a very useful resource :)

      It is on my to-do list to add more snippets. If you have time feel free to add a pull-request to the GitHub repository (sass-mixins) and I’ll merged it in ASAP.

  12. Awesome, you had my mind blow at the responsive breakpoints. That will go straight to the toolbox. Thank you very much.

    • No worries Fredric!

      Enjoy.

  13. These are fantastic, thanks for posting this.

    In my opinion 16px is best equated to 1rem, not 2. Here’s my own version for others who might be looking:

    
    @mixin font-size($sizeValue: 12 ){
            font-size: $sizeValue + px;
            font-size: (0.0625 * $sizeValue) + rem;
    }
  14. My first mixin, what do you think?

    
    @mixin border($direction,$size, $type, $color) {
    	@if($direction == "none") {
    		border: $size + px $type $color; 
    	}
    	@if($direction == "top") {
    		border-top: $size + px $type $color; 
    	}
    	@if($direction == "left") {
    		border-left: $size + px $type $color; 
    	}
    	@if($direction == "right") {
    		border-right: $size + px $type $color; 
    	}
    	@if($direction == "bottom") {
    		border-bottom: $size + px $type $color; 
    	}
    }

    Plz don’t kill me :)

This post currently has 40 responses. What do you think?

You can use basic HTML when posting code, please turn all < characters into &lt; or > into &gt;
If the code is multi-line, use <pre><code></code></pre>

Leave a Reply

Your email address will not be published. Required fields are marked *