Skip to content

Instantly share code, notes, and snippets.

@chriseppstein
Created January 4, 2012 22:08
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save chriseppstein/1562442 to your computer and use it in GitHub Desktop.
Save chriseppstein/1562442 to your computer and use it in GitHub Desktop.
This gist describes a new feature we're experimenting with for Sass 3.2: placeholder selectors. They do not get generated into your output, but they can be used like a class and extended like one.
$gutter: 10px;
$grid-unit: 60px;
%clearfix {
*zoom: 1;
&:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
}
%column {
@extend %clearfix;
float: left;
margin-right: $gutter;
&.last {
margin-right: 0;
}
}
@for $i from 1 through 9 {
.span-#{$i} {
@extend %column;
width: $grid-unit * $i + $gutter * ($i - 1);
}
}
.span-1, .span-2, .span-3, .span-4, .span-5, .span-6, .span-7, .span-8, .span-9 { *zoom: 1; }
.span-1:after, .span-2:after, .span-3:after, .span-4:after, .span-5:after, .span-6:after, .span-7:after, .span-8:after, .span-9:after { content: "\0020"; display: block; height: 0; clear: both; overflow: hidden; visibility: hidden; }
.span-1, .span-2, .span-3, .span-4, .span-5, .span-6, .span-7, .span-8, .span-9 { float: left; margin-right: 10px; }
.last.span-1, .last.span-2, .last.span-3, .last.span-4, .last.span-5, .last.span-6, .last.span-7, .last.span-8, .last.span-9 { margin-right: 0; }
.span-1 { width: 60px; }
.span-2 { width: 130px; }
.span-3 { width: 200px; }
.span-4 { width: 270px; }
.span-5 { width: 340px; }
.span-6 { width: 410px; }
.span-7 { width: 480px; }
.span-8 { width: 550px; }
.span-9 { width: 620px; }
@StanAngeloff
Copy link

@chriseppstein I saw it like so:

button {
  border-radius: 10px;
  @media print { border-radius: 0; }
}

@virtual button {
  border-radius: 10px;
}

.print {
  @virtual button {
    border-radius: 0;
  }
}

.my-button { @extend button; }

==>

button { border-radius: 10px; }
@media print {
  button { border-radius: 0; }
}

.my-button { border-radius: 10px; }
.print .my-button { border-radius: 0; }

@chriseppstein
Copy link
Author

nope. still don't get it. it's ok. I don't think there's an analogy to be drawn here. If you're connecting these dots, I think you're missing something.

@jlong
Copy link

jlong commented Jan 5, 2012

@chriseppstein All analogies break down at some point. And similarity is in the eye of the beholder. :)

@chriseppstein
Copy link
Author

Well I think if you form a mental model of this feature with an association to media bubbling it will cause you to reason incorrectly about it. So no, I don't think there's an eye of the beholder thing here. Having helped defined the concept means I can say this. Whether you like the concept we've defined or think another concept would be better is certainly a topic for further debate.

@nex3
Copy link

nex3 commented Jan 5, 2012

@jlong Your module example definitely has some interesting ideas, but it also has some aspects that I'm pretty wary of. What you're proposing is, like Chris said, basically a Sassy take on an object system, complete with multiple inheritance and overriding. While these systems are very powerful, they also bring along a huge amount of complexity. In order to understand them, the user has to wrap their head around a number of fairly abstract concepts.

Although in some sense placeholder selectors are a pretty radical idea on their own -- we certainly don't add new syntax lightly -- they have the undeniable virtue of being easy to explain and understand. Where your module proposal has a lot of extra functionality, placeholder selectors are just "extendable selectors that don't get rendered," and that's exactly what's needed for the specific use case we're addressing.

I guess my point is just that I don't want to overreach and add a more complex feature that I'm not sure is necessary, rather than a simpler feature that neatly solves the problem at hand.

@jlong
Copy link

jlong commented Jan 5, 2012

@chriseppstein What do you think we are missing? @StanAngeloff's example seems to illustrate the concept of the cascade and the similarity to @media bubbling well.

@nex3 I guess I just favor a more explicit syntax for this rather than a symbolic syntax. My module proposal is only to illustrate where you might take this if you venture in that direction. It would not need to be implemented all at once or in the same way.

The heart of my proposal for placeholder selectors is to use a keyword that is a noun. As demonstrated above you can still achieve the same cascade semantics as the symbolic method. Why not be more explicit? That seems to be the approach Scss favors.

@chriseppstein
Copy link
Author

@jlong I think you're missing how a placeholder selector can be used in any selector, not just as the core definition of a class and not just in a nested block of selectors. This is one of their strengths and what makes them exactly like classes (except for not being output). This is a new primitive concept in sass and as such it is more explicit than the original @silent/placeholder proposal I made, where one line in one file could cause a single class to become a placeholder and no indicator of this would be visible when reading the source. A more verbose syntax that would be analogous to what we've implemented here would be .foo::placeholder or placeholder(.foo).

@jlong
Copy link

jlong commented Jan 5, 2012

@chriseppstein I may be missing something. Can you show me a good example of "how a placeholder selector can be used in any selector, not just as the core definition of a class"? I'm struggling to understand why the keyword syntax can't do the same thing.

@jlong
Copy link

jlong commented Jan 5, 2012

"This is a new primitive concept in sass and as such it is more explicit than the original @silent/placeholder proposal I made, where one line in one file could cause a single class to become a placeholder and no indicator of this would be visible when reading the source."

@silent .button { ... }
.button { ... } // more rules for button, also silent because of the directive above
.my-button { @extend .button }

Is this what you mean?

If so, your original proposal makes a class selector silent and I agree that this is problematic. I propose a named group of rules -- not a selector.

@nex3
Copy link

nex3 commented Jan 5, 2012

@jlong In general, I prefer explicit syntax over symbolic syntax as well. The fact that placeholder selectors are obscure and not self-documenting is certainly their greatest shortcoming. However, in this case, the various proposed explicit syntaxes all have pretty significant downsides relative to placeholder selectors, and I think that those concerns outweigh the explicitness.

Specifically, proposals of the form @silent .foo { ... } require a lot of repetitive silencing and are contrary to the usual semantics of directives. Your @module syntax is as I mentioned complex to wrap one's head around; it's still not clear to me how you'd use it to provide for example a library of extendable classes. The most convincing factor for me was that in the end, all of the other proposals were ultimately just indirect ways of expressing "this selector should be a placeholder," which placeholder selectors express directly.

@chriseppstein
Copy link
Author

@jlong, yes, that is what I mean. And it's one of the reasons we didn't end up merging that changeset. A named group of rules is a mixin. but at the point that it's in the document it needs to have a selector to be addressable by extend.

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