Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ampersands in :not selector #1741

Closed
blimmer opened this issue Nov 16, 2015 · 2 comments
Closed

ampersands in :not selector #1741

blimmer opened this issue Nov 16, 2015 · 2 comments

Comments

@blimmer
Copy link

blimmer commented Nov 16, 2015

In the process of upgrading to libsass 3.3.x, I noticed that a (potentially incorrect) selector I was using before was no longer working.

Sass in question

.header {
  .nav-text-link:not(&.popover-link) {
    margin: 10px;
  }
}

Libsass 3.3.2 (invalid css)

.header .nav-text-link:not(&.popover-link) {
  margin: 10px; }

Libsass 3.2.5

.header .nav-text-link:not(.popover-link) {
  margin: 10px;
}

However, I realized that my use of the ampersand character in that :not selector was actually incorrect from the beginning. What I wanted was really:

.header {
  .nav-text-link:not(.popover-link) {
    margin: 10px;
  }
}

Ruby 3.4.14

Out of curiosity I ran the original sass (with the ampersand) against Ruby 3.4.14 and got this output:

.nav-text-link:not(.header.popover-link) {
  margin: 10px;
}

So there's definitely (at least) a bug with libsass leaving an ampersand in compiled css. Then there's the issue of what the "correct" interpretation of a nested ampersand in a :not selector is.

@mgreter
Copy link
Contributor

mgreter commented Nov 16, 2015

Thanks for the report. Handling of the :not pseudo selector is somewhat special and incomplete in libsass, as the following samples illustrate (I know we also need to add some implementation somewhere in and around unify_with). Basically we don't eval stuff inside wrapped selectors. Once you add an interpolation to a selector, we will evaluate and re-parse it (which btw. gives me a headache for source-maps), so in this case the parent selector will actually be resolved (see second sample).

foo#{b+ar} {
  :not(&#{'.bar'}) {
    color: #{baz};
  }
}

So this will actually work somewhat (libsass keeps the .header selector):

.header {
  .nav-text-link:not(#{&}.popover-link) {
    margin: 10px;
  }
}

I could probably patch just that issue by explicitly parentize wrapped selectors in the eval stage. But I really would like to understand why :not does what it does.

Some excerpt from current w3c specs: "The negation pseudo-class, :not(X), is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument. It represents an element that is not represented by its argument. Negations may not be nested; :not(:not(...)) is invalid. Note also that since pseudo-elements are not simple selectors, they are not a valid argument to :not()." ... "A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class"

Basically what ruby sass produces is invalid css and browsers should ignore it (Firefox emits this warning for me, sorry it's german: "Abschließende ')' fehlt in Negations-Pseudoklasse '['. Regelsatz wegen ungültigem Selektor ignoriert.")

So the question is why you really want to use something like this in the first place.

//CC @chriseppstein what is the stand here for ruby? IMO the only way to get a valid selector is when we only have one parent selector (also attribute selector will not work) that merges into another typeselector, as with foo { :not(&bar) ... }, which should in my intuition result in foo :not(foobar) ..., but will currently yield :not(foobar) ... in ruby sass!? Btw. AFAIK we have similar issues with :has "pseudo selector".

@mgreter
Copy link
Contributor

mgreter commented Jan 13, 2016

Fixes on latest master and will be in 3.3.3.

@mgreter mgreter closed this as completed Jan 13, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants