Html.Attributes.style
does not support setting custom properties. For e.g. the following won't work:
style "--alert-text-color" "#123456"
attribute "style" "--alert-text-color: #123456"
re: Passing variables to CSS, Setting the gutter
However, it doesn't work well when other styles need to be set. For e.g. the following doesn't work:
H.div
[ style "background-color" "black"
, attribute "style" "--alert-text-color: #123456"
]
re: It doesn't stack
The use of attribute "style"
overwrites the previous styles value set by style
. Order is important
when using this solution to ensure you don't overwrite previously set styles. So the following works:
H.div
[ attribute "style" "--alert-text-color: #123456"
, style "background-color" "black"
]
I personally don't see it as a problem since the only time I'd want to be using the HTML style
attribute
in my Elm code is when I want to use custom properties. For other uses of the HTML style
attribute I think
CSS classes in an external stylesheet are better suited.
If you really need to set both then the following snippet provides a workaround:
styles : List (String, String) -> H.Attribute msg
styles =
HA.attribute "style"
<< String.join "; "
<< List.map (\(name, value) -> name ++ ": " ++ value)
Now you'd be able to set custom properties along with other properties in any order you'd like:
styles
[ ( "border-color", "green" )
, ( "--circle-x", String.fromInt position.x ++ "px" )
, ( "--circle-y", String.fromInt position.y ++ "px" )
, ( "border-width", "3px" )
, ( "--circle-diameter", String.fromInt diameter ++ "px" )
, ( "background-color", "pink" )
]
If you only need to set a bunch of custom properties then we can make it so that you don't have to type all those "--" at the beginning.
customProperties : List (String, String) -> H.Attribute msg
customProperties =
HA.attribute "style"
<< String.join "; "
<< List.map (\(name, value) -> "--" ++ name ++ ": " ++ value)
For e.g.
customProperties
[ ( "circle-x", String.fromInt position.x ++ "px" )
, ( "circle-y", String.fromInt position.y ++ "px" )
, ( "circle-diameter", String.fromInt diameter ++ "px" )
]
There is a hacky solution I figured out after I stumbled upon the use of an HTML <style>
element in
elm-css.
H.div []
[ H.node "style" []
[ H.text ":root { --theme-background-color: #3241AF; }" ]
]
For e.g. I used this approach in my elm-2048 clone to control the tile movement duration from Elm.
The problem with this solution is that it uses an HTML <style>
element in the <body>
element. According
to the HTML Standard the
<style>
element should only be used
In a
noscript
element that is a child of ahead
element.
However, browsers may not really care according to Jukka. 😕
Elm doesn't provide support for CSS custom properties out the box. However, there are a few acceptable workarounds that I've mentioned that you can use for now. I'd be interested to learn about other scenarios where these workarounds won't work.
Examples of scenarios I haven't tried:
- CSS frameworks that can be configured with CSS custom properties
- Web components that can be configured with CSS custom properties
- Support for CSS custom properties
- Bug: CSS Custom Properties can't be set
- CSS Custom Properties
- Html.Attributes.style
- Html.Attributes.attribute
- A Complete Guide to Custom Properties
- The style element
- Developer-friendly alternative to
Html.Attribute
, which can handle conditional attributes, CSS custom properties, and more