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!

35 thoughts on “Handy Sass Mixins”

  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;
    }
    • 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.

  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. A good tip, prefix your own mixins with x- or something similar. Found this to be helpful when distinguishing between the built-in mixins, Compass (or other libraries) and your own. Some good suggestions here, thanks. E.

  6. 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.

  7. 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 šŸ˜‰

  8. 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.

  9. 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.

  10. 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;
    }
  11. 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 šŸ™‚

    • Steve,

      Web development is all about considering the trade-offs. You did a great job establishing the foundation for this particular border mixin. While considering what was traded by using your border mixin as opposed to using border, border-left, border-top, border-bottom, border-right. The trade-off I’ve notice is now my syntax would look like @include border(top, 2, solid, rgba(255,255,255,1)); In this tradeoff though I am now typing more to accomplish the same task. Now as I stated earlier you created an awesome foundation, I say this for two reasons:

      First, you now have a repeatable way of applying a border to your elements. This mentality will play a huge factor in being confident of your decisions while you code.

      Second, you created an awesome foundation for unique borders. How about refactoring it for “Vertical Lines” (Top & Bottom)? How about “Side-Lines” (Left & Right) or a “top-right-angle” (Top & Right)(There are 3 other combinations). You may never need them but the point of the mixin is to be a tool for any occasion.

    • See, the problem with SASS mixins is abuse by front-end developers who are programming novices, or have no programming experience at all (and no, HTML and CSS is not programming). This is a completely pointless mixin. The amount of code you have written is vastly disproportionate to any benefit. In fact, there is absolutely no benefit.

      @include border(top, 2, solid, #FF0000)

      vs

      border-top: 2px solid #FF0000

      Your mixin is actually longer to write and makes your CSS less readable. This is not what a mixin is for.

  12. Hi Jake,

    There are some good mixins there, thank you for this article.

    About the border-radius mixin, I think it can be simplified a lot, no need for all these if/else. This is the mixin I did based on yours:


    @mixin border-radius($radius, $border-positions...) {
    $border-position-found: false;
    @each $position in $border-positions {
    $border-position-found: true;

    -webkit-border-#{$position}-radius: $radius;
    border-#{$position}-radius: $radius;
    background-clip: padding-box; // Impide que el bg color salga fuera del border
    }
    @if $border-position-found == false {
    -webkit-border-radius: $radius;
    border-radius: $radius;
    background-clip: padding-box;
    }
    }

    So you can use it like this:


    .button {
    @include border-radius(5px, top-left, bottom-right);
    }

    You have more flexibility, and you reduce the include to one line.

Comments are closed.