mnussbaumer / cssex

An Elixir based and opinionated way to write CSS
MIT License
20 stars 0 forks source link

Stricter rules for ampersand usage #12

Closed mnussbaumer closed 3 years ago

mnussbaumer commented 3 years ago

This is not how it works in SCSS though. It was already working as it works in SCSS, but I think it's bad. In SCSS you're free to concatenate whatever you want but I've seen this used before and I ended up re-writing the stylesheets because what it does is break completely the readability of the chain. To illustrate.

.test {
    &--is-something {
           //....
           &--and-else {

           }
    }
}

What you end up is 3 different classes, one .test, another .test--is-something and another .test--is-something--and-else. This also means that now to search for these in files, you need to search only for the bits you want, you can't grep for .test--is-something--and-else. If it's used in a single place it's ok, the problem is that if you're using this pattern, you'll probably use it in many more places, and usually, because these "addendums" are descriptive (which kinda hints that these should be subclasses of a parent class), you end up using the same/similar names which makes searching for them, again harder, and you need to keep reading back the chain whenever you're reading the stylesheet, so I don't think it's a pattern that should be incentivised. I think perhaps, a good compromise is allowing the parser to have two modes, one where it allows it and another where it doesn't. Disallowing it also means the parser can error/warn when you try to concatenate two tags and tell you, this won't work:

div { 
  &p {
  }
}

Would either result in divp or pdiv. Disallowing it though, allows one to write

.test {
    &p {
    }
}

And get p.test {}.

div {
    .test & {
    }
} 

Results in .test div {}. It kinda is cute, but I'm not sure stuffing selectors inside a block when they should be outside is a gain, seems just like lazy writing so I might back off and remove support for it (or allow conditionally as an option). The & when used in a pseudo element though would still work independently of that.

div {
    .test {
      :not(&) { }
      :is(&) { }
    }
}

Would result in div {}, div :not(.test) {} and div :is(.test). Also seems lazy but less so, still confusing.