Disallow @extend within directives#154

Labels

Milestone

Assignee

7 participants

As per discussion in #96, @extend behaves in unintuitive ways when used within directives such as @media. Since there's no acceptable way to resolve this behavior short of browser-supported @extend, we'll just disallow it.

The plan is to add a deprecation warning in 3.1.x and change that to a full-on error in 3.2.

@ZeeAgency That's pretty tangential to this issue, but no, currently we don't have any concrete plans for that. We're tossing around ideas for a more advanced @import mechanism that may allow for file-scoped @extend in the future, but the details remain to be seen.

As an alternative to disallowing @extend within @media, do you see any issues with duplicating the selector when used across a different media query scope and then only merge those that are scoped within the same media query? For example:

Off-hand I can't think of scenarios in which this would behave in an unintuitive way. The processing could be smartened up further to exclude the additional reappearance of .test when the base class is defined outside a media query:

@gxclarke this is an interesting idea and theoretically sound, but it's more than just copying the base class, it's all the selectors that involve the .test class and if those are in media queries... well it gets complicated fast.

@chriseppstein This stuff seriously changed the way I write code (wrote an unpublished article and framework about this). File size seems better when preprocessing @extend although native mixins would do wonders for CSS size.

To push just a little harder to why I think this is such an important, here is an excerpt from an article I am working on explaining how @extend is saving me tons of K on file size when used correctly. Basically nothing is written unless it is used and @extend on @media is the crux of my responsive mobile first workflow with no fixed breakpoints:https://gist.github.com/2430955

When used improperly @extend can add a lot of code, but it is helping me keep my file size way down.

Because the actual base CSS objects are never written to save space, there would be nothing to extend inside media queries making this implementation impossible outside of preprocessors. From this mobile first approach almost every use of @extend will exist inside of a media query and the original object never written to the CSS.

@scottkellum It's not a logic issue, it's a bloat issue. It's dangerous to have a construct that produces a relatively manageable amount of output in most contexts but hugely more in certain specific contexts. To say nothing of the potential behavioral issues of re-ordering the document.

For your case in particular, it really feels as though all the %width-* rules should be mixins. Conceptually, they aren't classes to be inherited, they're just presentational rules. Is there a reason that they're placeholder selectors? Is it just for code size?

I also think you should be able to use placeholders and @extend in media queries as long as the placeholders have been defined in said media query. When you think about it, it makes sense : media queries create a sort of frame — a different environnement, while in the same CSS.

Sass should just aknowledge that and treat the media queries as a separate environnement, and while still able to use @extend, if you'd went and try to extend a placeholder/selector that is outside the media query, it would just throw an error.

@aaronjensen unfortunately I would like to reuse the same grid objects throughout the breakpoints fluidly instead of generating a set of objects for each breakpoint.

Also, extending from within the @media directive with the rest of your styles results in cleaner CSS output. These directives add a fair amount of weight to a page and the goal is to write one for each breakpoint. Excessive media bubbling can result in duplicate @media declarations.

@scottkellum I'm not sure what you mean by "Excessive media bubbling" or "duplicate @media declaration". Could you clarify? My proposal doesn't involve any additional @media declarations, and it keeps all of the style about one rule in one place, so it's easier to understand.