lxsmnsyc / solid-styled

Reactive stylesheets for SolidJS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

FYI, performance of attribute selectors is (relatively) poor

jorroll opened this issue · comments

commented

I'm so excited that this library exists! Thanks for publishing it!

Just wanted to pass along some info which you may or may not already be aware of:

I notice that this package is using attribute selectors to scope the CSS. This is the same approach Angular uses to scope component css but it differs from the approach taken by the styled-jsx package.

Something you may or may not already know is that attribute selectors have poor performance relative to other selectors. Since css is interpreted right-to-left, in some cases this package's use of attribute selectors won't make much of a difference, but in other cases it will.

For example, div[data-s-xxxx] theoretically has worse performance than just div and also worse performance than div *. Meanwhile, div[data-s-xxxx].myClass has performance dictated by myClass so the use of the attribute selector shouldn't matter. I say "theoretically" because this isn't something I've benchmarked personally but I've read a few articles now that have consistently placed attribute selectors at the bottom in terms of performance.

Of course, given that Angular successfully uses attribute selectors to scope css, I'm guessing the current approach is fine. But as someone who has used Angular a lot, I also don't consider it the most performant framework so it's not obvious that it's something to emulate. Either way, I expect very few websites will be large enough for attribute selector vs class selector to matter (and I don't expect it will matter for me, personally).

commented

I can see how the current approach simplifies the implementation though (no need to worry about a dev overwriting all the css classes of an element). And if someone was running into a performance concern, they could address it by just using a class or ID selector to control which selector is the "right most" one (i.e. div[data-s-xxxx] vs div[data-s-xxxx].myClass). So it seems quite possible that the current approach is the right one when balancing for complexity vs payoff.

I notice that this package is using attribute selectors to scope the CSS. This is the same approach Angular uses to scope component css but it differs from the approach taken by the styled-jsx package.

There was some considerations. Initially, I wanted to use classes much like styled-jsx, but I just realized that there's three ways to manage classes in Solid: class, className and classList. The behavior of merging classes is of uncertainty and I just didn't want to bet on it.

Something you may or may not already know is that attribute selectors have poor performance relative to other selectors. Since css is interpreted right-to-left, in some cases this package's use of attribute selectors won't make much of a difference, but in other cases it will.

I didn't know this, but interestingly, Vue uses the same method of scoping, so probably the performance isn't that of a huge difference. Take note that the article was written in 2011, 11 years ago. Browsers has changed a lot by then.

But as someone who has used Angular a lot, I also don't consider it the most performant framework so it's not obvious that it's something to emulate.

There's a lot of factors as to why Angular isn't the most performant framework, something like attribute selectors shouldn't be impacting its general performance.

commented

Take note that the article was written in 2011, 11 years ago. Browsers has changed a lot by then.

I hadn't noticed this and you're quite right. I've read similar information in other places, but it does seem quite possible that this is no longer accurate.

The behavior of merging classes is of uncertainty and I just didn't want to bet on it.

That makes sense. And, ultimately, if someone did have a performance concern they could fully address it by making sure a class selector is to the right of this library's scoping attribute selector.

Thanks again for making this. Such a great library!!!

I think this is worth revisiting. Here’s a post from 2022 that measured attribute selectors as up to 10× slower than class selectors.

The post has been updated to indicate that part of this performance difference may have since been closed by browser fixes, but some of these fixes are very recent, one being in Safari ≥ 16.0 which still excludes almost half of Safari users today.

Solid’s behavior of merging class with classList is documented:

It's also possible, but dangerous, to mix class and classList. The main safe situation is when class is set to a static string (or nothing), and classList is reactive. (class could also be set to a static computed value as in class={baseClass()}, but then it should appear before any classList pseudo-attributes.) If both class and classList are reactive, you can get unexpected behavior: when the class value changes, Solid sets the entire class attribute, so will overwrite any toggles made by classList.

We can stay within the documented safe situation by concatenating our static class name onto class.

@andersk Based on that same article

image
image

so my point still stands, we are at that point where browsers have already improved (except Safari maybe).