9.6 Sass extend
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 .overlay
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 overlay()
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.