CSS Custom Properties

Continuing the discussion from Improved documentation for flags, ports, and custom elements:

Evan asked in the aforementioned thread about why CSS Custom Properties should be exposed from Elm, and what value they provide over Elm variables.

Interaction with Web Components

Web Components have a shadow DOM, meaning that CSS from the page can’t affect the inside of the component. However, we sometimes want to style components.

Custom Properties penetrate the shadow DOM, something that can’t be done any other way. Many components I have seen therefore offer them as a way to affect the internal style of the component. This can be seen in some examples I have run into:

Fundamentally custom properties are a part of interoperability with web components.

This also exposes a point that CSS Custom Properties are not just variables, they inherit through the DOM like other CSS properties. While (unlike the above) this is possible to emulate if you control all parts of the page, if you are a child to other content that does use them, you can’t utilize the information.


Further to interoperability with web components, CSS frameworks also use custom properties, and where they do, clearly having access to custom properties facilitates working with them.

As an example of this, FontAwesome uses CSS custom properties in their CSS, which becomes an issue as detailed in my elm-fontawesome package.

Separation of style and content.

Fundamentally, a CSS custom property is a part of the style sheet rather than the content. If you extract the variable into your elm code, that styling becomes a part of your application and the content rather than the style sheet. This means users can’t use custom style sheets depending on that property, for example.

If Elm variables are the only option, you essentially get forced to use inline styles everywhere, otherwise whenever you need a variable you have to refactor your CSS into inline styles, which can be a lot of work when combined with things like media queries.

Future APIs depend on CSS Custom Properties.

CSS Properties are a core part of the Houdini APIs, and the only way to interact with some of them.

(As a side note, the Houdini APIs include the CSS Typed Object Model bringing types to CSS Custom Properties.)

Existing places this has been discussed:


Can you share an example of the code you want to write but cannot? Maybe in an Ellie like this one? It’s fine if it doesn’t 100% work. I just think that’d help me understand all the different cases better.

I think from there the best thing is to share those examples here, and then link to them from the open PR you linked in the other thread. That way we can find those documented examples later on.

1 Like


That is an example of changes that can only be made to the web component by using custom properties, done as it would be ideally and also using a work-around to show what is trying to be achieved.

As mentioned previously, another example can be found in this issue on elm-fontawesome, where the FontAwesome library provides duotone icons where each tone can have its opacity and colour set independently, using custom properties. This has an image example of what is being aimed for, a code example using the work-around and how it’d work given support for custom properties.

One of my other points was for user stylesheets, and clearly there isn’t really an example to give there: any time you use inline styles the user can’t override them without resorting to huge hacks which impairs accessibility.

With Houdini, you can see an example masonry layout here which is only configurable via custom properties.


Thank you @Latty for making a great case for support CSS custom properties and thank you @evancz for considering it.

Adding to the information already present, that I wholeheartedly agree with, another thing that you can do with CSS variables that you cannot do without is use them inside CSS: https://ellie-app.com/8FHJrtr82zRa1


There is another use case for custom CSS properties: the width of a dynamic grid table has to be set explicitly to guarantee the sticky first column.


This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.