How to do CSS in elm?

insertRule is definitely the way to go when thinking about CSS-in-elm. It is really powerful.

@mdgriffith we ended up with the same solution: atomic CSS with one property by class, reduces the number of classes generated. It’s a very good solution to decrease the processing time of the rendering.

2 Likes

Interesting! Do you support media queries this way? If so, I’m curious how you solved the problem of consistently ordering their output. I came up with a theoretical solution but haven’t tried it.

@rtfeldman, when @edkv uses Html.Styled.Lazy, the list items styles (I should have used ul and li for more clarity) are not merged anymore at the ul level like they are when lazy is not used (because a lazy node becomes a VirtualDom.Styled.Unstyled one), leading to a lot of duplicate style nodes:

Without lazy:

<ul>
<style ... />
    <li>...</li>
    <li>...</li>
    <li>...</li>
    ...
</ul>

With lazy:

<ul>
    <li><style .../>...</li>
    <li><style .../>...</li>
    <li><style .../>...</li>
    ...
</ul>

From a theoretical point of view, I struggle to see why lazy nodes have to be Unstyled and can’t pass their styles up. Is this something that could be optimized?

This is unfortunate, because the time we gained from not re-computing the element elm view by using lazy, it seems we lose it in the browser using the individual <style> nodes, except with Firefox Quantum. This makes lazy less attractive when using Html.Styled.

We’re supporting media queries through our DSL, but didn’t worked on ordering the output, because the problem never came up. But the point is definitely to solve in the future.

VirtualDom.lazy (which Html.Styled.Lazy uses under the hood) only accepts VirtualDom.Node, so to prevent recalculation of styles we need to somehow convert them to a VirtualDom.Node to be able to feed them into VirtualDom.lazy – to render them to a style element. So no, it’s not possible to avoid it unfortunately.

3 Likes

Thank you, I get it. Then the best I found to restore performance using elm-css with this use case is to use global styles (using Css.Foreign):

https://ellie-app.com/p5h8sfD3Ca1/3

(Note that empty <style> nodes are still rendered, maybe this could be removed).

This is not so bad even if not ideal, as it can be limited to elements rendered a lot. This is effectively an issue that elm-body/elegant most likely does not have by using insertRule.

So to answer the initial question, it seems that elm-body/elegant won’t have a straightforward way to migrate to 0.19 that maintains its performance, until a way to use insertRule is added to elm core, which is not currently expected for 0.19 first release, right?

1 Like

Well, I think elegant can send styles to JS via a port and then apply them with insertRule there instead of using the native code.