The Benefits of Inheritance via @extend in Sass

Share this article

Organizing CSS stylesheets has become crucial to styling large scale websites effectively, but stylesheets in our projects have been getting larger, more complex and harder to maintain as they develop. This is where Sass comes in to make everything simpler.

For those who have yet to explore Sass, it is an extension of CSS. It provides features for us that do not exist in native CSS such as expressions, variables, nesting, mixins (Sass’ name for functions), inheritance, and more.

In this article I’m going to give an overview of inheritance in Sass using @extend. I’ll cover the advantages this feature brings and my experiences when using it in my own projects. It is important to note that @extend can be misused, Hugo Giraudel here at SitePoint even wrote a piece on Why You Should Avoid Sass @extend. So be aware that @extend can be a contentious subject.

In the following examples, I will use the SCSS syntax. This is the syntax which contains all the features and structure of CSS, with Sass’ additional features.

What is @extend?

@extend is a feature of Sass that allows classes to share a set of properties with one another. Selectors that @extend a class in Sass will have their selector included right up next to the class it is extending, resulting in a comma separated list.

Its syntax looks like so:

@extend .class-name;

Usage

Using @extend looks like so:

.foo {
  color: black;
  border: 1px solid black;
}

.bar {
  @extend .foo;
  background-color: red;
}

This is compiled to:

.foo, .bar {
  color: black;
  border: 1px solid black;
}

.bar {
  background-color: red;
}

In the example above, I defined .foo and .bar which have the following features:

  • .bar inherits from .foo, containing all properties of parent class .foo.
  • .bar extends .foo by adding the property background-color.

Knowing the basics, we will now look at some use cases for @extend.

Using @extend

Use Case 1: Duplication

Duplication of properties between classes is hard to avoid when putting together CSS. This can make your stylesheets more complicated. For example:

.breakfast {
  color: #333;
  border: 1px solid #bbb;
  box-shadow: 1px 1px 0 #ddd;
  margin: 0 0 10px;
  padding: 15px;
}

.lunch {
  background-color: yellow;
  color: #333;
  border: 1px solid #bbb;
  box-shadow: 1px 1px 0 #ddd;
  margin: 0 0 10px;
  padding: 15px;
}

.dinner {
  background-color: orange;
  color: #333;
  border: 1px solid #bbb;
  box-shadow: 1px 1px 0 #ddd;
  margin: 0 0 10px;
  padding: 15px;
}

As we can see in the example above, .breakfast, .lunch and .dinner contain the properties color, border, box-shadow, margin and padding with the same values. These properties are duplicated, making our code look messy, so let’s rewrite it with @extend:

.meal-box {
  color: #333;
  border: 1px solid #bbb;
  box-shadow: 1px 1px 0 #ddd;
  margin: 0 0 10px;
  padding: 15px;
}

.breakfast {
  @extend .meal-box;
}

.lunch {
  @extend .meal-box;
  background-color: yellow;
}

.dinner {
  @extend .meal-box;
  background-color: orange;
}

In the rewritten CSS above, we can see that using Sass helps our markup become cleaner than CSS alone.

See the Pen Duplication of Properties in SCSS by SitePoint (@SitePoint) on CodePen.

Case 2: Moving Multiple Classes out of HTML

There are often cases when designing a page when one class should have all the styles of another class. We often handle this case by using multiple class names in the HTML.

Our CSS would look like so:

.candy {
  background-color: black;
  border: 1px solid red;
  box-shadow: 1px 1px 0 #ddd;
  padding: 15px;
}

.strawberry-candy {
  background-color: #ff6666;
  color: white;
}

Our HTML for that CSS:

<div class="candy strawberry-candy">
  This is the strawberry candy!
</div>

In the example above, we have two classes in our <div>. Imagine how messy this would be if we had several classes:

<div class="candy strawberry-candy sugar-free-candy free-candy">
  This is just an example
</div>

The HTML code above could become quite complex. Some web developers prefer it this way, however I prefer inheritance in my Sass styles:

.candy {
  background-color: black;
  border: 1px solid red;
  box-shadow: 1px 1px 0 #ddd;
  padding: 15px;
}

.strawberry-candy {
  @extend .candy;
  background-color: #ff6666;
  color: white;
}
With our HTML now looking like so:
<div class="strawberry-candy">
  This is the very sweet candy!
</div>

This time we only need one class. All styles defined for class .candy are also applied to class .strawberry-candy, now our HTML code becomes cleaner.

See the Pen Moving Multiple Classes out of HTML with @extend by SitePoint (@SitePoint) on CodePen.

Case 3: Extending complex selectors

Class selectors are not the only things that can be extended. We can also extend complex selectors into a single element, such as a:hover, .parentClass.childClass and so on. For example:

.example {
  color: black;
}

.example:hover {
  color: red;
}

.hover-link {
  @extend .example:hover;
}

This is compiled to:

.example {
  color: black;
}

.example:hover, .hover-link {
  color: red;
}

Which we can then use in our HTML like this:

<p>This is an example sentence with <a class="example">a sample link</a>
that should have a typical hover style.</p>
<p>This is another sentence, this time with 
<a class="hover-link">an eternally hovered link</a>.</p>

See the Pen Extending complex selectors with @extend by SitePoint (@SitePoint) on CodePen.

Advantages of @extend

Walking through the examples above, we can see several advantages of inheritance via @extend. These include:

Cleaner HTML Classes

As you can see in the second case study, using so many classes in one element may make it hard to determine the root cause if you run into issues. The structure of HTML tags also does not look very nice and clean.

From my point of view when making a good product, we consider not only the perspective of end-user but also the quality of our development strategy. Therefore, @extend helps us structure our classes in a cleaner way within each HTML element.

Reducing Duplication of CSS

In web development, we always have some duplication within our CSS styles. Hence, reusing written CSS source code can be extremely necessary. @extend can help us reuse our CSS when it is appropriate and cleaner to do so.

Saving time and effort

With the two aforementioned advantages, developers can save time and effort whilst developing.

Developers can reuse CSS for various elements, reducing the effort needed to find the root cause of CSS issues and making their CSS structure nice and clean.

However, using @extend is not without its dangers. The above advantages only apply when @extend is used carefully — it can be overused causing the opposite effect.

The Dangers of @extend

I have applied @extend in my own projects and I need to provide a word of caution when using @extend. You have to be careful.

@extend can increase your CSS file size drastically and impact the performance of your CSS when used without care. I had my share of pain in a situation just like this and spent lots of time refactoring my Sass’ use of @extend. Here is an example of how I initially used @extend incorrectly:

Example:

.base-css {
   color: red;
   font-size: 15px;
   font-weight: bold;
 }

 .btn {
   @extend .base-css;
   padding: 5px;
 }

 .warning-message {
   @extend .base-css;
   background-color: red;
 }

 .footer {
   @extend .base-css;
   color: #fff;
 }

 .content {
   @extend .base-css;
   margin: 10px;
 }

is compiled to:

.base-css, .btn, .warning-message, .footer, .content {
  color: red;
  font-size: 15px;
  font-weight: bold;
}

.btn {
  padding: 5px;
}

.warning-message {
  background-color: red;
}

.footer {
  color: #fff;
}

.content {
  margin: 10px;
}

In this example, .base-css is a class with many inherited classes based on it. If you take a look at the example, you can see that the inherited classes are not related to each other. I have .btn for my buttons and .footer for my footer. If I have 100 classes inheriting from .base-css, the selectors which have .base-css characteristics will increase. This significantly and unnecessarily complicates our CSS end result. Moreover, this makes it more difficult to check the properties of each selector.

After re-factoring my Sass, I realised that we should only use @extend when the inherited class directly relates to the object we are inheriting from. It should be a variation of the object or style, rather than a blanket rule for many unrelated elements. For inheritance like my example above, we should rely on CSS’ existing capabilities to cascade our styles into child elements.

.btn {
  color: #fff;
  font-size: 15px;
  font-weight: bold;
}

.btn-success {
  @extend .btn;
  background-color: green;
}

.btn-warning {
  @extend .btn;
  background-color: orange;
}

.btn-info {
  @extend .btn;
  background-color: blue;
}

.btn-error {
  @extend .btn;
  background-color: red;
}

is compiled to:

.btn, .btn-success, .btn-warning, .btn-info, .btn-error {
  color: #fff;
  font-size: 15px;
  font-weight: bold:
}
.btn-success {
  background-color: green;
}

.btn-warning {
  background-color: orange;
}

.btn-info {
  background-color: blue;
}

.btn-error {
  background-color: red;
}

We can see that the above example is much more correct and reasonable. We have reduced the scope by applying @extend only to classes that should inherit from one another due to being a variation of a type of object. For example, the above styles are all related to differing types of buttons.

Conclusion

Sass is a valuable extension that can improve our CSS to make it cleaner, well-structured, organized and easy to develop and maintain. If you have not tried Sass before, I highly recommend it. When you feel more comfortable with the basics of Sass, we recommend reading Hugo Giraudel’s SitePoint article on What Nobody Told You About Sass’s @extend. We also have an entire Sass reference guide at SitePoint’s Sass Reference with plenty of examples for you to explore.

Thank you to Steve and Ezekiel in the comments for picking up an error in the first version of this post, it has since been updated.

Frequently Asked Questions (FAQs) about Inheritance via Extend in Sass

What is the main advantage of using @extend in Sass?

The primary advantage of using @extend in Sass is that it allows for code reusability, which leads to cleaner and more maintainable code. It enables a class to inherit the styles of another class, thereby reducing the need to write repetitive code. This not only makes the code more readable but also reduces the file size, which can improve the load time of a webpage.

How does @extend differ from @mixin in Sass?

While both @extend and @mixin in Sass allow for code reusability, they work in different ways. @extend allows a selector to inherit the styles of another selector, whereas @mixin includes a block of styles that can be reused throughout the stylesheet. The key difference is that @extend generates less CSS output as it groups selectors with the same styles together, while @mixin can lead to more CSS output as it duplicates the styles each time it is included.

Can I use @extend with complex selectors in Sass?

Yes, you can use @extend with complex selectors in Sass. However, it’s important to note that @extend will only work with selectors that are present in the same file. It will not work with selectors that are defined in a different file or those that are generated by a @mixin or a function.

Why am I getting an error when using @extend inside a media query in Sass?

In Sass, you cannot use @extend inside a media query to extend a class that is defined outside the media query. This is because @extend works by grouping selectors with the same styles together, and it cannot do this across different media query blocks. To work around this, you can define the class you want to extend inside the same media query block.

Can I use @extend within a nested rule in Sass?

Yes, you can use @extend within a nested rule in Sass. However, it’s important to note that the extended selector will be inserted at the top level of the stylesheet, not within the nested rule. This is because Sass follows the CSS rule that all selectors must be at the top level of a document.

How can I avoid the “extend directives may only be used within rules” error in Sass?

This error occurs when you try to use @extend outside a rule set in Sass. To avoid this error, ensure that you are using @extend within a rule set. For example, instead of writing “@extend .class;”, you should write “.new-class { @extend .class; }”.

Can I use @extend with pseudo-classes in Sass?

Yes, you can use @extend with pseudo-classes in Sass. However, it’s important to note that @extend will only extend the styles of the pseudo-class, not the pseudo-class itself. This means that if you use “@extend :hover;”, it will not add a hover effect to the selector, but will instead extend the styles of the :hover pseudo-class.

Why is my @extend not working in Sass?

There could be several reasons why your @extend is not working in Sass. One common reason is that the selector you are trying to extend is not present in the same file. Another reason could be that you are trying to extend a selector within a media query or a nested rule, which is not allowed in Sass. Make sure to check these points if your @extend is not working.

Can I use @extend with multiple classes in Sass?

Yes, you can use @extend with multiple classes in Sass. You can do this by separating the classes with a comma. For example, “.new-class { @extend .class1, .class2; }” will extend the styles of both .class1 and .class2.

Is it possible to override the styles of an extended class in Sass?

Yes, it is possible to override the styles of an extended class in Sass. You can do this by defining the new styles after the @extend directive. The new styles will override the styles of the extended class for the selector that is using @extend.

David NguyenDavid Nguyen
View Author

David Nguyen is a front-end developer and UX/UI designer. He loves new technologies and is a big fan of Javascript. Beside that, he is also a Judoka.

extendpatrickcsasssass extendSass Extends
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week