rtfeldman / elm-css

Typed CSS in Elm.
https://package.elm-lang.org/packages/rtfeldman/elm-css/latest
BSD 3-Clause "New" or "Revised" License
1.23k stars 196 forks source link

Different behavior for multiple`css` attributes between root of tree and children #558

Closed micahhahn closed 2 years ago

micahhahn commented 2 years ago

I noticed some strange behavior that I'm pretty sure should be considered a bug.

If I specify multiple css attributes on the root node of a DOM tree that will get passed to toUnstyled then only the last call to css gets applied. See the following example:

main =
    Browser.sandbox { init = (), update = \_ -> identity, view = view >> toUnstyled }

view : () -> Html Msg
view _ =
    div
        [ css [ backgroundColor (hex "0000FF") ]
        , css [ color (hex "FF0000") ]
        ]
        [ text "asdf" ]

This produces text that is red, but does not have a blue background.

image

Also it's interesting here that two class names are produced, but only one has any css styles associated with it:

image

If, however, we apply the css attributes to a child node instead of the root we see both styles applied:

view : () -> Html Msg
view _ =
    div []
        [ div
            [ css [ backgroundColor (hex "0000FF") ]
            , css [ color (hex "FF0000") ]
            ]
            [ text "asdf" ]
        ]

image

Which resolution is correct?

There are a couple comments in VirtualDom.Styled.elm that suggest that the overriding behavior is intentional:

-- NOTE: Styles should always result in a classname, because they
-- can be detected later.
-- This way img [ css [ foo bar ], css [] ] wipes out the styles
-- as expected. (The latter will generate a classname of "_unstyled")
-- NOTE: Do String.isEmpty classname and not List.isEmpty styles
-- so that img [ css [ foo bar ], css [] ] wipes out the styles
-- as expected. (The latter will generate a classname of "_unstyled")

However, we seem to rely on being able to apply multiple css attributes quite heavily at NoRedInk. This seems to be the more useful behavior.

micahhahn commented 2 years ago

Note: I discovered this when trying to convert some views to use lazy. Since lazy passes its node immediately to toUnstyled this was breaking complex styles that came from multiple different css attributes.