styled-components / elm-styled

Styling your Html Elements with typed Css 💅
MIT License
179 stars 8 forks source link

Replace Native JS Code #14

Open k15a opened 7 years ago

k15a commented 7 years ago

I recently realized that only the elm-lang/core package is allowed to have native JS code. Currently elm-styled is using native JS code to inject the CSS. The problem is that I can't publish elm-styled to the official package manager and users would have to install this package directly from GitHub with tools like elm-github-install. The last couple of days I thought how to remove the native code from elm-styled to finally publish the package. My current solutions are:

Monkey Patching Element.prototype

This would work similar to https://github.com/gdotdesign/elm-html-styles. We would add a new attribute setter to the element prototype and everytime an element is created the styles would inject magically.

Usage

The user would have to inject a single script which monkey patches the elment.prototype.

Pros

Cons

Ports

Usage

  1. Setting up the model to hold all of the rules. (similar to https://github.com/evancz/elm-sortable-table)
  2. Creating a port module and injecting the styles with JavaScript on the other site. / Injecting the styles into a single style tag (probably pretty slow)
  3. Calling styled with an additional argument which is the Msg type to add styles to the model.

    type Msg
        = AddStyle Styled.Msg
        | OtherMsg
    
    styled
        AddStyle div
        [ padding zero
        ]

Pros

Cons

I would love the get some feedback and suggestions for better solutions. Maybe someone with more elm experience has a great solution for us.

leskeg-zz commented 7 years ago

I am a beginner in Elm but I have an idea...

As far as I see the main problem is injecting the CSS in the HTML. Css.js could be translated to Elm module, and for the function insertStyleSheet you could use node from Elm VirtualDom package somehow: http://package.elm-lang.org/packages/elm-lang/virtual-dom/2.0.4/VirtualDom#Node

I have done a small POC and works good:

module App exposing (..)

import Html exposing (text)
import VirtualDom exposing (node)

main =
    node "style"
        []
        [ text 
            """
            body {
                background:red;
            }

            @media (max-width: 600px) {
                body {
                    background: green;
                }
            }
            """ 
        ]

The only con of this is that style tag is inserted on the body instead of head, but browsers support this: http://stackoverflow.com/questions/1362039/style-and-script-tags-in-html-body-why-not

I hope it helps, by the way thanks for the elm implementation of styled-components!

gdejohn commented 7 years ago

Maybe instead of trying to shoehorn the benefits of sheet.insertRule() into a pure Elm package, we should be lobbying Evan to make this the way to do CSS in Elm. This approach seems terrific to me. Are there downsides that I'm not seeing?

baransu commented 7 years ago

https://github.com/elm-lang/virtual-css just got public and it may be good fit for replacing Native code. I really don't know how it's done right now but virtual-css seems excellent for that.

EDIT: This is unreleased yet and I guessing it will be part of the 0.19 release as well as https://github.com/elm-lang/browser

k15a commented 7 years ago

I will take a closer look in the future but that looks very promising. Thank you for notifying me.

justgage commented 7 years ago

Maybe look at this libarary as well to figure out how it does it: http://package.elm-lang.org/packages/mdgriffith/style-elements/latest

k15a commented 7 years ago

@justgage last time I took a look at styled elements they used inline style attributes to add the styles. This is a problem because they don't support keyframe animation pseudo selectors / classes and media queries.