garden icon indicating copy to clipboard operation
garden copied to clipboard

Atomic Styles

Open groundedsage opened this issue 7 years ago • 13 comments

I stumbled onto this project the other day and think it would be a perfect fit for the Garden ecosystem. It would be great to optionally have styles turned into atomic styles as a performance optimisation.

https://ryantsao.com/blog/virtual-css-with-styletron

My programming chops are still maturing but if there is any low hanging fruit that can bring this into being I am willing to have a crack at it.

groundedsage avatar Dec 25 '16 13:12 groundedsage

This was brought up in the garden slack channel on Clojurians. The v2.0.0 branch (see #123), once merged, will expose a CSS AST which can be manipulated using the stock Clojure library which means this kind of thing should be doable in a clean way. I'm still on the fence as to whether or not Garden should be responsible for doing any kind of heavy optimization though.

noprompt avatar Jan 05 '17 18:01 noprompt

If anyone can think of a way for garden to have add-ons or plugins of its own, heavy optimization would be one great (optional) feature, as would elaborate style cljs (e.g. #113)

WorldsEndless avatar Jan 05 '17 19:01 WorldsEndless

Yea that would be awesome. Garden would then essentially become the PostCSS of the Clojureverse

groundedsage avatar Jan 05 '17 23:01 groundedsage

Cross referencing https://gist.github.com/rauhs/ac6349dd20f1799982a1906f9a59e7d6

groundedsage avatar Jan 13 '17 23:01 groundedsage

So Styletron is marketed as a low level API and other CSS in JS solutions seem to be either wrapped over it or planning to wrap over it. I'm just wondering whether it would be best to wrap it. Seems like it will be a lot easier now. https://twitter.com/swannodette/status/823897912514146304

What do people think? I'm prepared to put some serious time into something like this but I want my time to be spent on an official solution that integrates nicely with Garden.

groundedsage avatar Jan 27 '17 13:01 groundedsage

@GroundedSage that would be really excellent!

brancusi avatar Feb 03 '17 19:02 brancusi

What's in #123 would allow this. I simply need help getting it over the finish line. I've been busy with work and family life and haven't been able to finish it up.

Perhaps I should schedule a hang out or something like that to get others involved. The slack channel and these GH threads seem like a pretty poor places to educate folks on the code and how to get involved.

noprompt avatar Feb 28 '17 18:02 noprompt

@noprompt yea a Google Hangout would be good. The format might need to be like a mini workshop or run through of everything and pointing out the key areas where you need help.

I've been busy as well.

groundedsage avatar Mar 01 '17 06:03 groundedsage

@GroundedSage

i just see your gist... thats awesome... see my challanges section in boot-atomizer

ya agree garden to replace PostCSS

i think we have common problem...
trying to improve expressiveness design and Developer experiences

1.use atomic classNames and css-shorthand 2.use macros to generate something 3.use vector or single entry-maps for css-shorthad

in garden use vector

[.h1 {:font-weight :bold} ]

how about writing like this?

{:font-weight "bold"} 
; just
{:bold } 

; key-values?  
{:padding "10px"}
{:border "1px solid red"}

;auto generating clasess
[.bold {:font-weight "bold"}]

styletron still generating names for classnames, thats bring pros and cons pros: smaller size cons: reuse globally see atomic css not generating others names use the sames

(defn component []
  [:div {:class "T(10px) P(1.6em) Translate(50%)"])

100% reuse..

azizzaeny avatar Mar 21 '17 17:03 azizzaeny

All credit goes to https://gist.github.com/rauhs/ac6349dd20f1799982a1906f9a59e7d6 I'm just working to have it work for my specific use cases and work with Boot.

I personally prefer having a 1 to 1 mapping when using css as it makes it easier to translate and interpret the code. It does bulk out the components a lot and requires more typing. But I find it to be less of a load on the brain to remember the mappings of class names to styles. It also means no work needs to be done to maintain the external mapping of class names or keep up with the spec.

[:img {:class [(css {:width "5rem"
                                :height "5rem"
                                :margin-right "2rem"
                                :margin-top "1rem"})]

           :src "photos/meetup-logo.png"}] 

There is a lot of circumstances where CSS shorthand shouldn't be used. So I often opt for using longhand. It also helps with code readability again. https://csswizardry.com/2016/12/css-shorthand-syntax-considered-an-anti-pattern/

For the purpose of code-reuse. I generally just define my styles elsewhere and then reuse with a symbol. Like this here.

(def meetup-text [(css {:flex-direction "row"
                                          :flex-wrap "wrap"})])

Say I was going to use this with the component above as an example. Along with some normal styles from a traditional CSS file.

  [:img {:class ["normal-styles"
                              meetup-text
                             (css {:width "5rem"
                                      :height "5rem"
                                      :margin-right "2rem"
                                      :margin-top "1rem"})]
           :src "photos/meetup-logo.png"}] 

The only downside of this current implementation is that it is a macro. Meaning I can't use say brand-color inside the (css ....) I could define these as mentioned above but I may want to use the brand-color for various things such as background-color, border-color, font-color etc etc. I also can't use any clojure or garden functions inside the macro so I can't do something like (lighten brand-color 20)

groundedsage avatar Mar 21 '17 23:03 groundedsage

Not sure how to actually format the code like normal clojure code in here...

Other additional considerations.

  • It would be cool to get all the above the fold content easily and inject that into the head.
  • Optimising the rendering could be done as well by ensuring all the layout styles are at the top of the CSS output.
  • Since garden is in CLJS it may be possible to make the atomic styles like Styletron super dynamic and even work without using React?
  • The styles can easily be injected into the head for making AMP (if people are making AMP sites). Which restricts the inline styles on head to 50kb??

groundedsage avatar Mar 22 '17 00:03 groundedsage

i think your approach is also good... we can compose those maps by making it outide of component...

(def small (css {:width "5rem"}]))
[:img {:class small }]

use specs like gamma :

(def spec {
   :smaller (css {:width "5rem"})
   :shadow (css {...))

[:img {:class (:smaller spec)]

or better instead calling css every component make single api and call onces

(def spec-tree {
   :smaller {:width "5rem"}
   :shadow {...}})

[:img {:class (:smaller spec-tree)]

; and render it 
(->
  (css spec-tree)
  (append-to-head) ; AMP styles OR PWA initial render offline
  (render-dom))

theming is done by spec macro api..

shorthands is anti pattern everywhere for those who write css even atomic css say it...

but we are using macros to generate string of string clj-string -> clj-string -> (process) -> css stuf postcss-shorthand is generating css directly my plan in atomizer

size(20,5/2) 

expanded to

w(20) h(5/2)

not direct css ya it is still poblem bring bloated but trade off simplicity...

instead clojure data strcuture, composing simple string is cool too...
we can type it with close eyes... :relaxed:

(defn component []
  (let [space "P(1.6em)"
        move  "T(10px) Translate(50%)"]
    [:div {:class (str space move)}]))

azizzaeny avatar Mar 22 '17 02:03 azizzaeny

@GroundedSage Use clj or cljs to format clojure(script)

  ``clj 
   ...
  ``

azizzaeny avatar Mar 22 '17 02:03 azizzaeny