Skip to content

Instantly share code, notes, and snippets.

@nex3
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nex3/e9640a78e417c046afee to your computer and use it in GitHub Desktop.
Save nex3/e9640a78e417c046afee to your computer and use it in GitHub Desktop.

When you write

.a .b .c .d {
  color: blue;
}

What you're saying is

Any element with class d that's nested beneath elements with classes a, b, and c in that order should have blue text.

Then when you write

.e .f .g .h {
  @extend .d;
}

what you're saying is

Any element with class h that's nested beneath elements with classes e, f, and g in that order should be styled as though it also has class d.

The conjunction of these two statements implies

And element with class h that's nested beneath elements with classes e, f, and g in that order and beneath elements with classes a, b, and c in that order should have blue text.

It's important to note that the two nesting requirements here don't have any particular order. Both of the following spans should have blue text:

<div class="a">
  <div class="b">
    <div class="c">
      <div class="e">
        <div class="f">
          <div class="g">
            <span class="h">Order 1</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<div class="e">
  <div class="f">
    <div class="g">
      <div class="a">
        <div class="b">
          <div class="c">
            <span class="h">Order 1</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

The way to represent this in CSS is

.a .b .c .d, .a .b .c .e .f .g .h, .e .f .g .a .b .c .h {
  x: y; }

Note that fully satisfying those semantics would produce exponential output, so Sass elides all but the two most likely permutations for space reasons.

@chriseppstein
Copy link

but in practice the mechanics of Sass have caused a lot of users to find themselves surprised by the need to think about it pretty hard

I think we've done a bad job at actually explaining what extend does. Most examples are very simple and they build a mental model that is based on a flawed understanding. Discovering that they misunderstood is a painful process, obviously. I don't think the solution is to not use @extend. I think the solution is that we explain selector inheritance more clearly so that people stop developing the wrong expectation in the first place.

@michaek
Copy link

michaek commented Aug 21, 2014

Even with an adequate understanding of how @extend works, increasing the number of selectors to cover the bases of what a user could possible mean makes it easier to bump into the <IE9 selector limit. The discovery is not so much that they misunderstood (misunderstanding being common enough that it's hopefully not painful!), but that the promise made by the feature - that the user shouldn't have to care about the CSS generated so long as Sass meets their semantic needs - is actually dangerous except in simple cases.

I haven't found it hard to understand what @extend does - my struggle is to understand why. @nex3 has given a good explanation of the reasoning in this case, but I haven't yet been able to find a CSS author who would ask for that behavior, let alone expect it. "The semantics I want should just work at any cost, and I should never have to think about the generated CSS" doesn't seem to be a widely-held sentiment among the developers I know. :)

@michaek
Copy link

michaek commented Oct 8, 2014

Hi, @chriseppstein and @nex3. I know I started this conversation before really getting into the @extend implementation in libsass, but even after completing the implementation, I'd like to discuss the possibility of simplifying the behavior of @extend. One of my team members described @extend like this: the tool isn't dangerous because it's sharp, it's dangerous because it's unpredictable.

A possibility that I've considered is adding an option to prevent @extend operating on anything other than placeholder selectors, enshrining that "conventional wisdom" as a compiler feature. Obviously, not everyone wants to extend only placeholders, so the option's default would retain the current @extend behavior.

A less sensible option is allowing a "naive_weave" function that eschews the philosophy of "the selector I'm extending from should work everywhere the selector I'm extending to does" in favor of string substitution. It's obviously not as powerful, but I think the power of @extend often works against CSS authors - not just because they don't understand @extend but because even with a good understanding it's very hard to reason around. (My terrible illustration of the concept: DealerDotCom/sass@fd4048e)

I don't disagree with the ideas and goals behind the current implementation and behavior of @extend. I think it's a really impressive solution to the defined problem. But I'd also like to imagine providing options that might give authors who prefer it an @extend with a smaller scope - a sharper tool that's easier to predict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment