Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Syntax improvements related to the `&` selector #286

Closed
chriseppstein opened this Issue · 97 comments
@chriseppstein

See #282 for the discussion leading to the creation of this umbrella issue.

@nex3
Owner

If we do something smart with & + &, how should we handle & > & or & &?

@chriseppstein

I don't think we should try to get into the business of understanding how to interpret combinators with &. Instead I think we should give better expressiveness about what is meant by the author.

For instance:

  • last-selector(&) + last-selector(&)
  • all-but-last-selector(&) > .foo > last-selector(&)

bad naming above is on purpose. Also, could consider using pseudo selectors instead of functions like &::last-component but this creates potential namespace collisions.

@nex3
Owner

I'm not opposed on principle to adding some way of using functions along with &, but we'd need to find a good syntax for it. This means something that has a low probability of conflicting with CSS, and ideally something that integrates well with our existing syntax.

Here's one possibility that has a small delta on our existing syntax: we allow & as a first-class object in SassScript that evaluates to the parent selector. This allows you to write standard functions that operate on selectors; e.g. & + #{last-selector(&)}.

@chriseppstein

It seems like if we are going to a make a literal that represents a selector in SassScript that we're close to allow storing a selector into a variable and allowing variables of type "selector" to be used without interpolation in selectors. I think this could be very attractive.

@nex3
Owner

Having selectors be a first-class type (that is, storing them in variables) is very, very different than allowing variables without interpolation in selectors. Once variables are allowed without interpolation somewhere, people will expect all of SassScript to work; see for example #284. There's no good way to support all of SassScript in a selector.

@chriseppstein

agree that these are separable concepts.

Trying to decide if I want to make a case for allowing a simple subset of SassScript that is Selector Safe™.

@chriseppstein

Adding #285 to the list of things to consider here.

@ZeeAgency

I may be wrong but what about a syntax like &(1) where 1 is the number of steps back in the selector nesting chain (not sure how to call it, hopes you understand what I mean...).

For instance :

.foo {
    .bar {
        & &(1) {
            a: b;
        }
    }
}

Would output :

.foo .bar .foo {
    a: b;
}
@nex3
Owner

I really hate the idea of having different subsets of SassScript work in different places. I'm already considering disallowing @media $foo { ... } in favor of @media #{$foo} { ... }.

@nex3
Owner

@ZeeAgency That feels like it's much harder to understand than it's worth, given how little it would be used.

@nex3
Owner

After talking this over with Chris, we're currently leaning towards having & be a SassScript expression referring to the current parent selector. Rather than have it be a string, we'd have it be a space-separated list of strings to make it easier to operate on with functions. I believe this, along with user-defined functions, would support all the use-cases brought up here.

@ericam
Owner

I was about to open another related issue, but I think it might fall under this one. The parent-selector (&) should not error-out on base-level rules. It should simply not reference anything.

Here's a sample use-case:

@mixin respond-to($media,$ie-class:'ie') {
  @media (#{$media}) { @content; }

  // We need the parent selector here in order to mimic the @media bubbling.
  .#{$ie-class} & { @content; }
}

// This works already.
.container { 
  @include respond-to('min-width: 30em') {
    color: red; 
  }
}

// This should work with exactly the same result.
// And it would without the error from parent-selector:
// "Base-level rules cannot contain the parent-selector-referencing character '&'."
@include respond-to('min-width: 30em') {
  .container { color: red; }
}

As it is, you can't create a mixin that works both in a nested and root context, which severely limits the mixin.

@ericam
Owner

@chriseppstein @nex3 - any thoughts on that? It's a blocker for the next Susy update, so it would be good to know if and when it might land. Thanks!

@alanhogan

This is currently the only open issue tagged v3.2. Is it the only blocker? When might 3.2 go stable?

@chriseppstein

We have one more feature for 3.2. It's variable argument passing to mixins and functions. And there's a pending pull request for giving warnings when an @extend doesn't match any selector.

@nex3
Owner

This isn't going to make it into 3.2. Re-tagging as 3.3.

@ericam
Owner

Even if Susy say's please?

@nex3
Owner

I'm trying very hard to get 3.2 out the door, which means avoiding any additional features.

@ericam
Owner

Ok, Susy will just look forward to 3.3 with longing and anticipation. :)

@phillip-haydon

Will this allow something like.

.search {
   .container& {
      // if .search is inside .container...
   }
}

To output:

.container .search {
   // styles
}

( just trying to understand what I'm reading in this issue to see if it solves what I want :) )

@nex3
Owner

@phillip-haydon You can do that today, like so:

.search {
   .container & {
      // ...
   }
}
@chriseppstein

Reminder: be sure that ruby functions can access the & in a script context.

@Grassboy

how about this case?

$C: ".module-"; //module class name prefix
#{$C}farther {
    color:red;
    #{$C}child {
        color:orange;
    }
    & #{$C}child { //same as previous block
        color:orange; 
    }
    #{$C}grand-farther & {
        color:yellow;
    }
    &#{$C}mother {
        color:green;
    }
}

the newest version of sass's output is below

.module-farther { /* css block 1*/
  color: red;
}
.module-farther .module-child { /* css block 2*/
  color: orange;
}
.module-farther .module-child { /* css block 3*/
  color: orange;
}
.module-grand-farther .module-farther { /* css block 4*/
  color: yellow;
}
.module-farther.module- mother { /* css block 5*/
/*NOTICE: there is a SPACE char between the 2nd. ".module-" and "mother" */
  color: green;
}

In css block 1~4, the result of string combination in css selectors are correct...

but the selector in css block 5 should be

.module-farther.module-mother 

rather than

.module-father.module- mother /* a space char before "mother" */

btw, from http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#id11 (sass reference: @for)
we can confirm that string combination in css selectors would be accepted

i know the '&' reference cannot be combined with other string
but in this case, the string combination should occurred between ".module-" and "mother"
it should be accept just like the selectors in block 1~4

so... can we regard this case as a bug of sass?


finally, please forgive me about my poor English... thanks...

@nex3
Owner

@Grassboy That happens because Sass doesn't understand what you mean when you do &#{$C}mother. It expects & to be followed by a simple selector (e.g. .foo, #bar); when it's followed by interpolation, it thinks you're just starting a new selector.

With this change, you'll be able to accomplish your goal by doing #{&}#{$C}mother.

@Grassboy

Thanks for your response...

i've found that the sass code can be modified as follow before #{&} is available

$C: "module-"; //module class name prefix
.#{$C}farther {
    color:red;
    .#{$C}child {
        color:orange;
    }
    & .#{$C}child { //same as previous block
        color:orange; 
    }
    .#{$C}grand-farther & {
        color:yellow;
    }
    &.#{$C}mother {
        color:green;
    }
}

then Sass would understand what i mean,
and i can modify my module name in the future easily in the future

@phillip-haydon

@nex3 this seems really fiddly. Given:

div.column {
    div.information {
      &:hover & {
          display: block;
      }
    }
}

I would expect the output

div.column:hover div.information {
    display:block;
}

However I end up with:

div.information:hover div.column div.information {
    display:block;
}

Seems broken or at-least doesn't do what I want it to do :(

@Grassboy

In div.information { ... }

the '&' character stands for "div.column div.information"

so, the block

div.column {
    div.information {
      &:hover & {
          display: block;
      }
    }
}

i guess it may generate

div.column div.information:hover div.column div.information {
    display: block;
}

under the optimization process, the result css may be reduced as

div.information:hover div.column div.information {
    display:block;
}

and maybe that's what you end up with

@nex3
Owner

@phillip-haydon As @Grassboy points out, & refers to the entire parent selector. There's no way for Sass to know that you want it to refer to subsets of that selector -- let alone which subset -- in the example you gave.

@brewster1134

I see that the additional feature of using the parent selector at the base-level is a future feature for 3.3...

...but does 3.3 have a time table? I dont see a milestone setup for it. I am eagerly awaiting this feature :)

@nex3
Owner

We generally don't commit to time tables, since Chris' and my schedules are generally pretty variable.

@brewster1134

Understood. More just curious. When you mentioned 3.3 I looked for a milestone to track issues against.

@kmontag

Not sure if this belongs in its own issue, but I'd love the ability to do something like the following:

+html-modifier(foo)
  color: blue
  +html-modifier(bar)
    color: red

Outputting:

html.foo { color: blue }
html.foo.bar { color: red }

Currently the closest I can get is:

=html-modifier($modifier)
  html.#{$modifier} &
    @content

However, this doesn't work at the base-level, and nesting the mixin generates rules like:

html.bar html.foo .selector { // styles }

Concretely, this would be useful for outputting separate styles based on e.g. different combinations of Modernizr detections, or different combinations of "theming" classes (like light/dark at http://compass-style.org/) applied to the HTML element.

@nex3
Owner

@kmontag this could be used for something like that, although it would probably require pretty heavy-duty processing on the part of the mixin.

@thesyd

is it posible?

.selector {
    .ie8 & { // property }
    //& plays ascendant role
}

css becomes

.ie8 .selector{ //property }

is there any feature in 3.3 to obtain from scss, something like .ie8 & { .child // property or child reference } to translate in css

.ie8 .selector .child { //property }
@nex3
Owner

Yes; that works right now.

@thesyd

how? if i may ask please

@Snugug
.selector {
  .ie8 & {
    .child {
    }
  }
}
@thesyd

this will result in
.ie8 .selector .child { }

what i was wonder if you can achieve a child of the .ie8 that reference it
.ie8 .child .selector { }
once you are in scss but without
.selector {
.ie8 .child & { }
}

@nex3
Owner

No, you can't.

@ibc

Some way to reference a parent would be useful. In my case I strongly miss something to improve the following syntax:

.parent {
  .child-1 {
    .child-2 {
      color: black;
    }
  }
}

.parent.selected .child-1 .child-2 {
  color: red;
}
@samilyak

I was really surprised so common css usecase @ibc described is such a mess in SASS. That's especially funny when

.parent{
  &.state{
    ...
  }
}

works, but

.parent{
  .child1{
    .child2{
      .state.&{ // or .state&
       ...
      }
    }
  }
}

doesn't work. Come on, I've just switched .state and &.
Anyway guys I love SASS (thanks for your work) and eagerly awaiting this feature to be implemented in 3.3.

@chriseppstein

Come on, I've just switched .state and &.

You're treating & as if it's just a string replacement. It's not. & is a selector that is parsed like an element name and as such, there are only certain place it is valid for it to be present in a syntactically-valid way for all uses of the value of &. String replacement is what #{} is for, and as such exposing & to a script context is the way we're going to tackle this project. The script parser has to be changed to know what & means and then we have to wire the selector context into the script context.

This is very high on the list of features we want to add. I actually started working on it the other day.

@millermedeiros

it would be good if we could manipulate the parent selector like a list, so we could potentially grab the last [n] selectors on the chain - eg. button#{tail(&)} inside .foo .bar would output button.bar.

@FWeinb

I thought about a way to better write BEM like CSS in SASS/SCSS.

The main idea is that it should be possible to write SCSS like this

.block{
    &__element{
    }
    &--modifier{
    }
}

to get this

.block{
}
.block__element{
}
.block--modifier{
}

I hope the new & selector will support this in v3.3. Or is there a better way to accomplish this?

@chriseppstein

@FWeinb Yes, This would work like this:

.block{
    #{&}__element {
      // ...
    }
    #{&}--modifier {
      // ...
    }
}
@FWeinb

Yeah, tried that but that didn't work for me.

See: http://codepen.io/FWeinb/pen/601856036197d62523038b1413a79b59

Error on line number: 2. Invalid CSS after "    #{": expected expression (e.g. 1px, bold), was "&}__element {"

I have tested it local with Sass 3.2.8 (Media Mark)

@chriseppstein

@FWeinb it will work in Sass 3.3.

This was referenced
@nex3
Owner

Chris and I ran into an issue with the implementation of this as sketched here. If you write foo { .bar#{&} { ... } } there's no good way for Sass to know that it shouldn't include .foo in the generated selector, yielding foo .barfoo { ... } instead of the desired .barfoo { ... }.

Our solution to this is to introduce a new directive, @at-root, which causes one or more selectors to be placed at the root of the document instead of being nested, while preserving the parent selector as the referent of &. So you'd write foo { @at-root .bar#{&} { ... } }, which would yield .barfoo { ... }. This is unfortunately verbose, but we think it's the best option.

It will also work without a selector, like so:

foo {
  @at-root {
    .bar#{&} { ... }
    .baz#{&} { ... }
    .qux#{&} { ... }
  }
}

Rejected Alternatives

Look For &

The first solution we considered was similar to what we do for non-SassScript selectors: look in the selector expressions and see if & is used. However, this breaks referential transparency, the principle that (in this case) $var: ...; #{$var} { ... } should always be equivalent to #{...} { ... }. This is because Sass would be unable to detect that a parent selector was being used in the code foo { $parent: &; .bar#{$parent} { ... } }.

"Parent Selector" Bit

We could try to track, for every SassScript value, whether that value is derived from a reference to the parent selector. This solves the referential transparency issues, but also adds a host of practical problems. Every SassScript operation and function, including third-party functions, would have to be aware of the parent selector bit and propagate it forward if necessary. Worse than the practical issues, though (in my opinion), is the issue of associating invisible and inaccessible information with an unremarkable-looking value.

Other Syntaxes

We talked about various different syntaxes for indicating that the parent selector should be omitted from a given selector. &:omit and :omit(&) were rejected for looking too much like plain CSS and for making it look like & could be replaced by a different selector. ::no-parent and ::no-& were rejected because the semantics of a pseudo-element didn't match well with the operation that was being performed. ^ was rejected because adding a completely new syntactic character bears a high cost and eats up syntax space that isn't worth it for what's ultimately a reasonably narrow feature.

Once we settled on the directive syntax, we also talked about different names. @no-parent was rejected because the parent selector & is still meaningful within the block. @no-auto-parent was rejected because of verbosity and because the nesting process isn't referred to as "auto parent" anywhere else. @unnested was rejected because nesting still occurs, it's just broken at one specific level. @bubble was rejected because the notion of "bubbling" is a reasonably advanced concept that we didn't want to presuppose knowledge of.

We chose @at-root because it didn't include a negation, which we thought caused confusion, and because it neatly describes the process of putting the selector(s) at the root of the document.

@ghost

Hello,

I've just update my version from 3.1.1 to 3.2.9.

Does this version includes the possibility to concatenate class names like this:

.badge 
   border: 1px solid black;
   &-info 
      background:blue;
  

to have a result as:

.badge { border: 1px solid black; }
.badge-info { background: blue; }

Or:

.bt,
.bp 
   border: 1px solid black;
   &-info 
      background:blue;

If this syntax isn't supported yet, how can I accomplish it? Have a huge amount of files in which I need to update the syntax.

Thanks!

@edwardoriordan

@avrilverhaeghen you can't with 3.2.9. Something like that you have above will work in Sass 3.3 (though not with the synax your using).

@svitaliyv

How can I install Sass 3.3 for work with "-" and "_" in class names?

@chriseppstein

The lastest code changes are available via gem install sass --pre.

@casio

@chriseppstein Just installed --pre, and tried:
#{&}__element { /*...*/ }

..but I still get:
Invalid CSS after " #{": expected expression (e.g. 1px, bold), was "&}__element {"

What would be the correct syntax?

@chriseppstein

@casio that change hasn't landed yet.

@nmiddleweek

Hey @chriseppstein, how you doing? Looks like a few of us are eagerly waiting for the 'SASS-BEM' syntax, this will be awesome when it's released so thanks for making this happen... I see you guys have it in a 'late' Alpha stage, when is likely to be a proper 3.3 release? Are we talking weeks or months? I'm just thinking of production sites.

Cheers,
Nick Middleweek

@chriseppstein
@alienresident

I have use/edge case that you may want to consider.

Due to poor system design, I need to override a style from a stylesheet that's called after mine. Mine is the 'skin' or 'theme' stylesheet and should be called last but it's not. I'm using CSS specificity to override the styles that come after.
I'd like to make a mixin to do this using the & selector but it doesn't quite work.

Mixin

@mixin specificity {
  & & {
    @content;
  }
}  

Sass

.whatever {
  @include specificity {
    border: solid;
  }
}

Outputted CSS

.whatever .whatever {
  border: solid;
}

Desired CSS

.whatever.whatever {
  border: solid;
}

Less than ideal workaround
In case anyone is looking for something similar or has a better solution here's my current workaround.

Mixin

@mixin specificity-2($selector) {
  &#{$selector} {
    @content;
  }
}

Sass

.whomever {
  @include specificity-2(".whomever") {
    border: solid;
  }
}

CSS

.whomever.whomever {
  border: solid;
}

This may indeed be an edge case but I thought I'd add it to the discussion.

Thanks,
Mark

@chriseppstein

@alienresident This would be possible to do in sass 3.3. like this:

@function index-of-last-class($selector) {
  $index: null;
  $counter: 1;
  @each $component in $selector {
    @if str-index($component, ".") == 1 {
      $index: $counter;
    }
    $counter: $counter + 1;
  }
  @return $index;
}

@function list-slice($list, $start, $end: length($list)) {
  $new-list: ();
  @for $i from $start through $end {
     $new-list: append($new-list, nth($list, $i), list-separator($list));
  }
  @return $new-list;
}

@mixin increased-specificity($selector: &) {
  $class-index: index-of-last-class($selector);
  @if $class-index {
    @at-root #{list-slice($selector, 1, $class-index)}#{nth($selector,$class-index)} #{list-slice($selector, $class-index + 1, length($selector))} {
      @content;
    }
  }
  @else {
    @warn "Cannot increase the specificity of #{$selector}. It does not include a class name.";
    @content;
  }
}  

Note: this does not currently work, even on the lastest code base, as it uses planned features.

@alienresident

Wow, thanks!
Look forward to it's implementation. Thanks for all you work. Sass and Compass have changed my life. I can now design in the browser.

UPDATE

@mixin specificity {
  &#{&} {
    @content;
  }
}

.whatever {
  @include specificity {
    border: solid;
  }
}

Produces

.whatever.whatever {
  border: solid;
}

In Sass (v3.3.0.rc.1)
See (SassMeister gist)[http://sassmeister.com/gist/7142577]

This is what's supposed to happen right?

@isnifer

@chriseppstein Hi. 2 months ago you told about bem-like syntax in 3.3.0. Today we have 212 alpha and we haven't this feature.
One question - when?

@pdaoust

@chriseppstein @nex3 What might happen with nested @at-root directives? (Real life situation -- I'm trying to do some sort of 'root class bubbling' to emulate 'media query bubbling' for Modernizr-style root classes. Note that a lot of these selectors and styles would be inserted via mixins; I've just flattened it out for demonstration purposes.)

.menu {
    @at-root .unresponsive-desktop & {
        li { display: inline-block; }
        a { display: block; background: alice-blue; height: 1.5em;
            @at-root .unresponsive-desktop.touch & {
                height: 40px; // Make the target large enough to press with a finger.
            }
        }
    }
}

I imagine this would create something like...

.unresponsive-desktop .menu li { display: inline-block; }
.unresponsive-desktop .menu a { display: block; background: alice-blue; height: 1.5em; }
.unresponsive-desktop.touch .menu a { height: 40px; }

My question is, do @at-root directives bubble/nest (remembering the containing @at-root directive's selector and adding it on), or do they always break out to root, ignoring the containing @at-root directive completely? Because I can imagine the above Sass code creating this, which isn't quite right:

.unresponsive-desktop .menu .unresponsive-desktop.touch a { height: 40px; }

Thanks; looking forward to this!

@chriseppstein

@pdaoust The value of & is unaffected by @at-root directives in any way. @at-root only tells sass to not do an automatic ancestor prepend to the immediate selectors within it. Or to the selector given as it's argument. To date, we haven't planned to allow both nested and inline selectors with @at-root

@chriseppstein

@iSnifer Probably another month or so according to plan.

@pdaoust

@chriseppstein So if I understand you correctly, my first example was the right guess?

@chriseppstein

No, first, it's using a syntax we don't intend to create, but accepting that I understand what you're trying to express it would end up creating: .unresponsive-desktop.touch .unresponsive-desktop .menu a

@pdaoust

I think I understand... so in the two examples where I'm using @at-root, because I have a & in the argument, it would be exactly the same as if I hadn't used it at all, right? As for the syntax you don't intend to create, do you mean I can pass the un-inherited selector as an argument, or have it as a child of @at-root, but not both?

.parent {
    @at-root .not-child { // okay
        color: blue;
    }
}

or

.parent {
    @at-root {
        .not-child { // also okay
            color: blue;
    }
}

but not

.parent {
    @at-root .not-child {
        color: blue;
        .not-grandchild { // not okay, because we've got selectors as arguments and children
            color: green;
        }
    }
}

So I'm guessing that @at-root is not intended for use cases like mine, eh?

@chriseppstein

@pdaoust Well, @at-root is what enables us to manipulate the value of & in SassScript. And in SassScript you could write a function like replace-primary-scope(&, ".unresponsive-desktop.touch")

@Grassboy

Execuse me? has this feature ( #{&} syntax) been available in
https://rubygems.org/gems/sass/versions/3.3.0.alpha.222 (sass 3.3.0.alpha.222) ?

@tagliala

It Seem it isn't...

I also need this feature to convert less stuff like

.responsive-visibility() {
  display: block !important;
  tr& { display: table-row !important; }
  th&,
  td& { display: table-cell !important; }
}
@nex3
Owner

This feature is still in development. It's not yet available on the master branch or alpha release.

@tagliala tagliala referenced this issue in diowa/twbs_sass_rails
Closed

TODO #1

@pdaoust

It seems to be in the master branch now, and available via gem install sass --pre as well. Looking good, and really useful for strange edge cases (which I seem to create a lot of in my day-to-day Sass writing), although I think there may be a couple bugs.

@tagliala

@pdaoust glad to hear, I will take a look asap.

What is the syntax to achieve (in less)

.class {
  a& { color: red; }
}

?

@pdaoust

That would be

.class {
    @at-root a#{&} { color: red; }
}

To give you

a.class { color: red; }

Keep in mind, though, that just like with Less, if you decide to nest it...

.wrapper {
    .class {
        @at-root a#{&} { color: red; }
    }
}

you'll get weird results:

a.wrapper .class { color: red; }
@chriseppstein

This landed on master recently.

@nex3
Owner

This has been implemented; @at-root development will be tracked in #774.

@khmelevskii

@at-root + #{&} + many nested = ugly syntax! This syntax in Stylus is beautiful

@gisu

Write a Mixin

@mixin c($name)
  @at-root
    #{&}--#{$name}
      @content

.myclass
  +c(child)
    height: 200px

Result
.myclass--child {
  height: 200px; }
@chriseppstein

@khmelevskii Every language has it's own benefits and drawbacks. Ours works this way for very good reasons. You're welcome to use stylus if it is a better fit for your stylesheets.

@joneff
body {
    color: black;
    #{&}.red {
        color: red;
    }
    &.green {
        color: green;
    }
}

compiles to

body {
  color: black; }
  body body.red {
    color: red; }
  body.green {
    color: green; }

Using Sass 3.3.0.rc.1 (Maptastic Maple) on Windows

@pdaoust

@joneff That looks like Sass is doing what it ought to; if this isn't what you expected, can you give us a sample of what you expected and we can steer you in the right direction with the new scriptable &?

@joneff

Reading trough the @chriseppstein 's comment (#286 (comment)), related to BEM implementation

.block{
    #{&}__element {
      // ...
    }
    #{&}--modifier {
      // ...
    }
}

I'd really expect both & and interpolated #{&} to work the same in this simplest of cases [and not to have duplication of the parent rule].

Actually it's the duplication of the parent rule that bothers me :)

@pdaoust

Ah, I see. What happens is that #{&} takes the parent selector and treats it as a value, so you can almost (not quite, but almost) think of it as a variable that holds the value of the parent selector. It would be almost the same as writing:

body {
    $parent-selector: #{&};
    #{$parent-selector}.red {
        color: red;
    }
}

Now you can see that, because the parent selector is stored as a variable and interpolated into the child selector, it becomes part of the tree and the parent selector gets added to it. What you want to do is break out of the parent selector completely, like so:

body {
    @at-root #{&}.red {
        color: red;
    }
}

That'll produce

body.red {
    color: red;
}

I think that Chris' comment #286 was written before @at-root and the scripted & had been solidified. The syntax has changed since then.

(Note: As you already discovered, your example would be the same as writing

body {
    &.red {
        color: red;
    }
}

so you wouldn't be getting any benefit from scripted &, but I assume that your actual code is more complex than your example.)

@szarouski

@chriseppstein Please take a look at following comment - #286 (comment) @FWeinb demonstrated that classes are not nested under parent class (that make sense, why would we bother adding parent to class which already have parent name as part of itself). Is there anything that can be done about it?

@szarouski

Sorry, I lost attention, that answers my question

.block{
    color: #000;

    @at-root #{&}__element{
      border: 1px solid;
    }
    @at-root #{&}--modifier{
      background: #fff;
    }
}
@pdaoust

@Serge-Z I thought I'd mention that support for this has been temporarily removed (see #1077) and will be added back in in Sass 3.4. So if you really need this (as I do) and don't mind some bloated output sometimes, stay with 3.3.0.rc2.

@nex3
Owner

Actually, as per #1055, it's even easier to do this with Sass 3.3:

.block {
  color: #000;
  &__element {
    border: 1px solid;
  }
  &--modifier {
    background: #fff;
  }
}
@pdaoust

@nex3 correct, after reading https://gist.github.com/nex3/8050187 I was just about to edit my response. Thanks for setting us both straight! :-)

@barneycarroll

I'm trying to qualify variations of the ancestor selector from within a nested chain.
Ideally, qualifying classes could be appended to the ancestor selector, but I don't believe this is yet possible with SASS – but by all accounts, I should be able to come up with the following using a half-way reasonable use of SASS nesting:

.delivery-option .icon {
  // Ancestor element styles 
}

.standard.delivery-option .icon {
  // Sprite 1
}

.unavailable.standard.delivery-option .icon {
  // Sprite 2
}

I've tried this:

.delivery-option {
  // Ancestor element styles 

  .icon {
    // Icon layout

    .standard& {
      // Sprite 1

      .unavailable& {
        // Sprite 2
      }
    }
  }
}

And I've also tried forcing interpolation with eg .standard#{&} and #{".standard"}#{&}.

I was using 3.3.0.rc.6, and just updated to 3.3.3. & is always a syntax error (most explicitly because "&" may only be used at the beginning of a compound selector.), any which way I try to achieve this. Has this regressed, or am I doing it wrong?

@chriseppstein

@barneycarroll we removed script access to & for the 3.3 release. See https://gist.github.com/nex3/8050187 for more information.

@hanoii

Is what @ibc commented above in #286 (comment):

Some way to reference a parent would be useful. In my case I strongly miss something to improve the following syntax:

  .parent {
    .child-1 {
      .child-2 {
        color: black;
      }
    }
  }

  .parent.selected .child-1 .child-2 {
    color: red;
  }

still impossible to do in a neat clean way? I would like to have color:red easily between .child-2 on the first block code instead of outside, I found reference to script & that might do it with a custom script, but I wonder if theres an easy way.

I also thought of the following, right now, if you do:

 .parent {
    .child-1 {
      .child-2 {
          .selected & {
             color: red;
           }
        color: black;
      }
    }
  }

outputs

.parent .child-1 .child-2 { color: black; }
.selected .parent .child-1 .child-2 { color:red }

which is not what you want, what about allowing for

 .parent {
    .child-1 {
      .child-2 {
          .selected& {
             color: red;
           }
        color: black;
      }
    }
  }

Not the ampersand is now without a space, the same as when you use it like that on the other side, this could outut:

.parent .child-1 .child-2 { color: black; }
.selected.parent .child-1 .child-2 { color:red }
@nex3
Owner

With selector functions, you can write

.parent {
  .child-1 {
    .child-2 {
      @at-root #{selector-append(".selected", &)} {
        color: red;
      }
      color: black;
    }
  }
}

and get the result you want.

@hanoii

@nex3, thanks, I didn't know that, is that on 3.3.9? as apparently it's not working there.

@nex3
Owner

No, it's a new feature for 3.4.

@artitudinale1

Is there any news about the possibility to use this kind of mixing:

    .#{$wrapper-class}  & {
          @content;  
     }

I'm using SASS 3.4.5 and seems to don't work.

@ryanjwilke

Maybe I skipped over something, but is there an easy way to get this result:

video .controls {
  color: red;
}
video.fullscreen .controls {
  color: blue;
}

out of something like this:

video {
  .controls {
    color: red;
    .fullscreen & {
      color: blue;
    }
  }
}

currently, that actually compiles to:

video .controls {
  color: red;
}
.fullscreen video .controls {
  color: blue;
}
@artitudinale1

I got this working

     @mixin respond-wrapper-fallback($name, $wrapper-class) {
             @at-root .#{$wrapper-class}  {
              @content;
                }
              @include respond-to($name) {
               @content;
               }
         }

and using as

         [class*='col-'] {
               width:100%;
               margin: 20px 0 15px 0;
               .grid &:last-of-type {
                         padding-right: 0;
                }
              @include respond-wrapper-fallback (tablet, old-ie&){
                        float: left;
                        padding-right: $pad;
                        margin:0;
                }
                 img{
                       width:100%;
                 }
         }

the output

       [class*='col-'] {
                  width: 100%;
                  margin: 20px 0 15px 0;
                   }
       .grid [class*='col-']:last-of-type {
                   padding-right: 0;
                 }
        .old-ie [class*='col-'] {
                     float: left;
                     padding-right: 50px;
                     margin: 0;
                     }
            @media only screen and (min-width: 767px) {
                [class*='col-'] {
                          float: left;
                          padding-right: 50px;
                          margin: 0;
                     }
              }
                [class*='col-'] img {
                          width: 100%;
                 }

basically using $wrapper-class& when I call the mixing - it does what I want but seems to me lil bit of an hack?!???

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.