porsager/bss

allow way to lift selector specificity

futurist opened this issue · 22 comments

when has something set in b.css using class as selector, it's very easy to override inline bss definitions.

Please see this demo

The li never be blue.

Is there any way to lift selector specificity?

That's a good point, although I think adding class specific styling like (ul.wrap li) using b.css kind of defeats the purpose of bss..

Techically bss could repeat the class twice to get higher priority.

To be honest I almost like that the example won't work since it exposes a potential dangerous global css class styling.

Would love to hear your use case for this?

The use case is easy to find, even in flems, like below line:

https://github.com/porsager/flems/blob/efa332291686d5e541a873d667ed158e961b10d5/src/styles.js#L16

You cannot set inline link color anymore!

I'm sorry, you are so right❗️😊
That right there has actually already resulted in a bug in flems 😆 Thanks for pointing it out 😉

I'll try to think about a better solution wrt. specificity than the above one.. Ideas are more than welcome..

Repeat the class is the resonable way, for performance, I think below is good for a test:

https://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/

https://github.com/benfrain/css-performance-tests

I made a test result of repeat class selector using above repo, please see attached results.

bss-repeat-class.zip

Conclusion: repeat 100 class selector version seems have no observable performance reduction.

Thanks @futurist.

This change will also solve the same issue for styles set with $nest if i make sure to not add the class twice when using nest!

I've got a fix almost ready.

Thanks a lot!

I've always used the following selector fragment to increase specificity:

:nth-child(n)

It's semantically null and always valid. Despite it looking hacky (everything is hacky for this feature – there is no semantically correct 'but more specific'), I feel it's a better indicator when reading the generated code: it's clearly done by intent, and with an understanding of the mechanic there's clearly nothing else it could be doing.

Ah, that's clever Barney! Hadn't seen that before, but now that we're improving, I think I like :root .className better.

I am still thinking about wether this will be a good idea to solve generally instead of having to solve it by adding an explicit specificity bumper method.

By that I mean always generate sheet selectors as :root .className unless it's applied using $nest. I think that would take care of most use cases, and of course we could also add a method to increase the number of :root:root:root added manually to bump specificity?

What do you think about that solution @futurist and @barneycarroll

I think :root is better, +1 for this

Thanks @futurist

@barneycarroll do you see any downsides to doing the :root thing generally?

Hey @barneycarroll .

I'd still love your input on the above (although this issue is closed), and before i release this change 😉

It looks nicer, but it won't work if the targeted element is the root. Given that BSS-generated selectors don't have any human readable semantics I think the comprehensive solution is better.

That's a good point Barney!

I just did some testing, and it seems neither :root nor :nth-child(n) can be used with the root (eg html). Only double class name seems to work. Am I doing something wrong, or are we back at doing the double class name solution ? 😜

sample here

classes and pseudos both have a selector specificity order of 2 (tagnames being 1, ids being 3, inline style being 4). Volume of any given one of those categories can trump another in the same order, but any of a higher order will trump them. Outside of that, order of declaration trumps all.

In your example @porsager you have 3 rules with competing property declarations, and all of them have selectors consisting of exactly 2 2nd-order selector components. Therefore, the last one will win out: pseudos don't trump classes, they're equivalent.

In order to increase specificity, we need a generic selector of that same 2nd order of power which can trump potentially later-defined classes by a step of 1. The example doesn't show that specificity increase.

The point I'm making is that if we increase that specificity by appending an extra semantically null entity, we have a procedural mechanism for increasing specificity that can be applied in any situation. And that can't be done by prepending :root because :root html is semantically invalid.

Here's the sample which shows that the :nth-child(n) mechanism works universally, whereas prepending :root won't work depending on whether or not the target is the actual root.

When all's said and done, the class duplication mechanism is probably better… I think

Ah, I see what's going on :P Try my or your example in safari ;) .test:nth-child(n) will never be applied on <html>.

It works in chrome though, which I didn't find out until I guessed that's why you saw it as working.

I know about the specificity, but I think browser incompatibilities just got the better of us ;) (obviously a safari bug in the case of :nth-child(n) not working).

LOL, of course. How condescending of me, to think that I could treat the primordial ancestor as a child! Classname duplication and concatenation best option then?

I'd like to use :nth-child(n) since your argument for it makes very much sense to me, but since I don't want to wait for safari fixes (haven't tested other browsers), I guess class name duplication is the way to go..

Haha 😀 Off we go 👍

Eh, actually I think that makes sense. The root element is not a child.

I noticed it's only repeat 2 times. How to add more repeation?

@futurist Yeah, that was to solve the most prevalent cases, and I'm leaning towards suggesting $nest(':nth-child(n), ...)' for adding specificity instead of making a dedicated method for it (eg. something like b.$priority(n) | b.$classRepeat(n)).

I'd love to hear your opinion and @barneycarroll 's as well, but my thinking is that if you're in a specificity war, it's never really gonna be pretty, so why encourage it?