blakeembrey / free-style

Make CSS easier and more maintainable by using JavaScript
MIT License
707 stars 29 forks source link

Proposal: Deterministic style order #61

Closed blakeembrey closed 6 years ago

blakeembrey commented 7 years ago

Currently styles are sorted by insertion time (with oldest insertions at the beginning). I'm considering a move for this to be deterministic by sorting styles by their identifiers. This would guarantee styles, no matter what, are always rendered the same. I have no statistics on whether someone has managed to hit a case where this has had any impact, but any thoughts?

At the very least it alters behaviour such as https://github.com/blakeembrey/free-style/issues/14, making a v3.0 candidate.

/cc @basarat @notoriousb1t @ajoslin

ajoslin commented 7 years ago

Do you know if other css-in-js engines do this? It seems like this could have unintended effects on selector priority in existing apps.

notoriousb1t commented 7 years ago

I think changing to this behavior would make it more difficult to compose generated styles together. While it would be more deterministic, I think it removes the ability for developers to impose their own order. Since people coming from CSS already expect that the order of rule-sets impacts what takes precedence, I think it might be very surprising.

I can appreciate the property ordering within a CSS rule-set because it only negatively affects one very small use case (that we actively discourage), but this kind of change would require a large mind-shift for some.

blakeembrey commented 7 years ago

That's a valid point, thanks. My concern arose thinking about the edge-cases of async loading external components - if each async loaded component added styles, you won't have any true guarantee of CSS ordering.

There's also a minor perf increase we could implement by changing the insertion order. If we switch to "first insertion always", we no longer need to re-order keys (but there's the linked issue downside). If we insert deterministically, we always know exactly the position it'll be in the style sheet.

As for other libraries doing this, I definitely haven't run across it. Combined with @notoriousb1t's point, it's probably a bad idea to change expectations here. Do any of you async load components and/or have this concern? I haven't really worked on a project where I've needed it myself, but I could see heavy componentisation in HTTP being an issue with style ordering.

notoriousb1t commented 7 years ago

I see the value of what you are trying to do; however, I think that because it changes expectations so much, a developer should have to opt-in or opt-out of it. Thinking out loud here, but either a configuration option for the instance or a ranking system could solve either of those issues.

blakeembrey commented 7 years ago

Absolutely, it's great to get insights for this reason 😄 I'll think about whether a flag is really worth it, I haven't seen any complaints (yet) and it might be more relevant if I go ahead and build an async component UI like that. What do you imagine the ranking system would look like? I was thinking the approach you guys recommend with &&, but I suppose we could codify it into a number and automate this.

notoriousb1t commented 7 years ago

I think it could be as simple as an importance/rank property that takes a positive number. if you need certain styles to proceed others, you could just assign them a higher number. In the case of async components, the developer can make this determination as they need to.

As far as implementation goes, I would imagine that the stylesheet could be split into logical segments where non-ranked styles are 0 and rules are appended to the end of their section. This type of feature would actually aid in making CSS more composable. I'm thinking of the .btn + .btn-full scenario in Bootstrap where default styles are overridden.

After writing all of that out, this sounds like it might be more of a pain than it's worth.