9.6 Sass extend

Sharing common properties

The common properties case

Sometimes you find yourself writing the same set of properties across different CSS rules.

For example, let’s say your design makes use of small spaced uppercase letters throughout the page: buttons, navigation bar, sidebar headings, tabs…

Something like this:

Small spaced uppercase letters

How would that look like in your CSS? You could:

  • use a common CSS class like .small-uppercase
  • combine the selectors
  • use a Sass extend

Common CSS Class

.small-uppercase{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

Having a .small-uppercase CSS rule is semantically incorrect because you’d end up writing your HTML as <p class="small-uppercase"> which reverts to basically writing styles within your HTML.

Combine the selectors

Because a CSS rule can accept any number of selectors, you could combine the shared properties under a list of selectors:

.button,
.navigation a,
.sidebar h3,
.tabs a{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

This approach remains semantically valid because each selector describes the HTML element they’re attached to.

However, there are 2 problems:

  • this CSS rule can become unmanagable as soon as the list of selectors becomes longer
  • because each selector has specific rules of their own, you’re separating your set of properties in two (the .button can have additional rules further down the CSS)

Sass helps solving these problems.

Sass @extend syntax

A Sass @extend allows to inherit CSS properties from another selector:

// scss
.small-uppercase{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

.modal-background{
  @extend .small-uppercase;
}

.product-link{
  @extend .small-uppercase;
}

.image-pattern{
  @extend .small-uppercase;
}

// generated css
.small-uppercase,
.modal-background,
.product-link,
.image-pattern{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

The @extend will regroup common properties under a list of selectors.

The list is easily maintainable because you only add selectors one by one, and directly in the related selector.

Your HTML remains semantic because each element keeps its descriptive class name.

Difference with mixins

Well, you might be thinking “Wait, isn’t it just like mixins then?”?

There are 2 differences:

  • The @extend rule doesn’t have parameters. Mixins do.
  • The @extend rule does combine selectors. Mixins don’t.

Let’s reuse our overlay mixin, and also write a .small-uppercase rule:

// scss
@mixin small-uppercase() {
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

.modal-background{
  @include small-uppercase();
}

.product-link{
  @include small-uppercase();
}

.image-pattern{
  @include small-uppercase();
}

// generated css

.modal-background{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

.product-link{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

.image-pattern{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

The list of properties is simply repeated as many times as the @include small-uppercase() is called.

A Sass @extend is more efficient, as it only writes the common properties once.

Placeholders

Well, you might be thinking “The .small-uppercase isn’t semantic! I could use it in my HTML!”?

You’re right, and that’s why placeholders exist in Sass.

If you don’t want or need the .small-uppercase selector, transform it into a Sass placeholder by replacing the dot with a percentage sign %:

// scss
%small-uppercase{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

.modal-background{
  @extend %small-uppercase;
}

.product-link{
  @extend %small-uppercase;
}

.image-pattern{
  @extend %small-uppercase;
}

// generated css
.modal-background,
.product-link,
.image-pattern{
  color: lightslategrey;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 12px;
  text-transform: uppercase;
}

Note that the generated CSS doesn’t include the .small-uppercase selector anymore. That’s because the %small-uppercase rule is only here to provide a location for common properties.

Difference between extend, placeholders and mixins

Definition Referencing Combines selectors? Allows parameters? Can be used on its own?
Mixins @mixin name() @include name() No Yes No
Extensions Any class @extend .class Yes No Yes
Placeholders %placeholder @extend %placeholder Yes No No

When in doubt, use mixins. They generate more CSS lines and are less elegant than extend/placeholders, but they are straightforward.

Back to top

The underlying source code used to format and display this website is licensed under the MIT license.

Powered by Jekyll. Hosted on GitHub.

Close