Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
338 views
in Technique[技术] by (71.8m points)

css - SASS and Bootstrap - mixins vs. @extend

I'm using the SASS port of Bootstrap, and I'm wondering if there's any difference between using the pre-defined mixins and using SASS's @extend.

For instance, if I have:

<div class="wrapper">
    Some content here....
</div>

Is there any difference between doing

.wrapper {
    @include make-row();
}

and

.wrapper {
    @extend .row;
}

?

If there's no difference, are there other mixins that aren't equivalent to a single @extend statement? If there aren't such mixins, why do the mixins even exist?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The big difference between @extend and a mixin is the way the css is compiled. It doesn't look like much in simple examples, but the differences and implications are significant and can be a real headache in the wild if used carelessly. @extend is a little bit like fools gold, looks great at first, but ...

Let's look at a simple example:

@extend

.row {
    width: 50px;
}
.new-row {
    @extend .row;
}
.another-row {
    @extend .row;
}

compiles into:

.row,
.new-row,
.another-row {
     width: 50px;
}

mixin

@mixin row() {
    width: 50px;
}
.new-row {
    @include row();
}
.another-row {
    @include row();
}

compiles into:

.new-row {
   width: 50px;
}
.another-row {
   width: 50px;
}

A mixin includes the properties everywhere it is hit - copying them each time - whereas an @extend groups the selectors and defines the properties once. This isn't immediately obvious, because the difference is in the compiled css but it has some important implications:

Load order

With @extend the selectors will be grouped at the first point in the sass where they are encountered which can lead to some weird over-riding. If you define a selector and use @extend to bring in a property to and try to override a property defined earlier in your sass, but after the point at which the extended properties are grouped in the css then the override will not work. This can be quite perplexing.

Consider this logically ordered set of css definitions and the likely HTML: <div class='row highlight-row'></div>:

.red-text {
    color: red;
}
.row {
    color: green;
}
.highlight-row {
    @extend .red-text;
}

compiles into:

.red-text,
.highlight-row {
    color: red;
}
.row {
    color: green;
}

So even though the sass ordering makes it look like the row colour would be red, the compiled css will make it green

Poor groupings

@extend can result in poorly grouped selectors in the resulting css. You can end up with thirty or forty unrelated things all sharing the same property for example. Using @extend for fonts is a good example of this.

Nesting

If you are using deeply nested sass (which is not good, btw) and you use @extend you will duplicate the fully nested selector for every @extend you use, resulting in bloated css. I've seen this a lot:

.selector-1 .selector-2 .selector-3 .selector-4,
.selector-1 .selector-2 .selector-3 .selector-4 a,
.selector-1 .selector-2 .selector-3 .selector-4 li,
.selector-1 .selector-2 .selector-3 .selector-4 td {
    font-family: arial;
}

If you're new to SASS it pays to look at the compiled css.

Media queries

@extend do not work inside media queries, because media queries are not selectors.

Conclusion

My rule of thumb is to use an @extend over a mixin if you have no parameters and if you can reasonably define the @extend and share it amongst a few tightly related selectors that exist nearby in the sass, for example, in the same file that defines a sass module. Buttons are a good example of well used @extend:

%button {
    padding: 10px;
}
.call-to-action {
    @extend %button;
    background-color: $green;
}
.submit {
    @extend %button;
    background-color: $grey;
}

The best article to help make the choice is here

PS, the % sign is a use of placeholder extends


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...