Object Oriented SASS (OOSASS) with Inheritance

 

Mixins in SASS are great, however, there is a downside to using them for your OOSASS. Mixins bloat the output code. Every time you call a mixin it includes the output of the mixin in your final CSS.  The obvious solution is placeholders, but placeholders don’t work well with parameters or with BEM-style css class names.

I’ve come up with a solution that solves both problems. I lets you use a mixin for your OOSASS class, it lets you inherit from this OOSASS class and also produces efficient output using placeholders.

Say we are styling the following markup:

  <article class="my-article">
     <h1 class="my-article__title">Title</h1>
     <p class="my-article__body">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est labour.</p>
  </article>

We might start by making a mixin for this component;

1
2
3
4
5
6
7
8
@mixin article {
   &amp;__title {
      font-size: 18px;
   }
   &amp;__body {
      font-size: 12px;
   }
}

And then use it:

.my-article {
  @include article;
}

The problem here comes when we try to apply this mixin to another component.

.another-article {
    @incluce article
}

This is going to output this, which duplicates our CSS:

.my-article__title {
   font-size: 18px;
}

.my-article__body {
   font-size: 12px;
}

.another-article__title {
   font-size: 18px;
}

.another-article__body {
   font-size: 12px;
}

What we want to do here is to create placeholders for every element in our mixin “class”, and use them with extend inside our mixin.

%article__title {
  font-size: 18px;
}

%article__body {
  font-size: 12px;
}

@mixin article {
  &amp;__title {
    @extend %article__title;
  }
  &amp;__body {
    @extend %article__body;
  }
  @content;
}

Now our previous code which did the @include article on the two components generates this:

.my-article__title, .another-article__title {
  font-size: 18px;
}

.my-article__body, .another-article__body {
  font-size: 12px;
}

Now I have a reusable mixin that produces optimized SASS!  But what if I want to override some style of an instance of a component? This is fine. Since we included @content in our mixin ‘class’ you can do this:

.another-article {
  @include article {
    &amp;__title {
      color: black;
    }
  }
}

So what we have here is in essence OOSASS. .another-article is an instance of article. And it add styling to the title to color it black. But what if we want to make  a subclass of article? Say we want it to be a featured article and have larger bolder headlines? We can do this:

%featured-article__title {
  font-size: 24px;
  font-weight: bold;
}

%featured-article__body {
  font-size: 16px;
}

@mixin featured-article {
  @include article {
    &amp;__title {
      @extend %featured-article__title;
    }
    &amp;__body {
      @extend %featured-article__body;
    }
  }
  @content;
}

featured-article inherits from article. It overrides font-size and adds font-weight. Here’s an example of using two articles and two featured articles

.an-article {
  @include article;
}

.another-article {
  @include article;
}

.a-featured-article {
  @include featured-article
}

.another-featured-article {
  @include featured-article
}

And the CSS output it produces:

.an-article__title, .another-article__title, .a-featured-article__title, .another-featured-article__title {
  font-size: 18px;
}

.an-article__body, .another-article__body, .a-featured-article__body, .another-featured-article__body {
  font-size: 12px;
}

.a-featured-article__title, .another-featured-article__title {
  font-size: 24px;
  font-weight: bold;
}

.a-featured-article__body, .another-featured-article__body {
  font-size: 16px;
}

Because of the single level of specificity of BEM, the overrides work perfectly the and later rules for font-size win for featured articles.  It would be nice to properly override the font-size and get it to exclude the first font-size declaration automatically, but sass doesn’t really provide a mechanism to do this sort of thing. Here’s a live example of the above on sassmeister if you want to play with it.