[ClojureScript] Re: CSS in CLJS
FWIW I did a quick test to see if things worked with reagent. Turns out they do. Basically works out of the box: https://github.com/thheller/reagent-test The dependency on Clojure 1.9 was not intentional and I would remove it if anyone wants to use this with 1.8. Anyways feel free to clone the test project and mess around, you get the whole figwheel experience + CSS without editing CSS files. /thomas -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Re: CSS in CLJS
As I said I haven't used garden, can't say how much of a difference there is. One thing I can't change is that selectors have to be strings, they are keywords in garden. The maps of css properties should be portable though and you shouldn't really need the selectors after? As for re-using css classes: Don't! That is the whole point of this, as mentioned here: http://mrmrs.io/writing/2016/03/24/scalable-css/ and elsewhere. I have been in this situation many times where I'm scared to touch an existing class since I have no direct record of who uses it in which situation. Or where I added another class with !important, just to have a quick fix somewhere. Also I hated OOCSS with things like where the actual order mattered and I never could remember which it was. You can and should however abuse all the power of Clojure. I have this for some of my styles: (defn button-style [env] {:padding 10 :border (str "1px solid " (-> env :colors :border)) :background-color (-> env :colors :bg)}) and then re-use this a couple time for anything that should look like a button: (defstyled link :a [env] (merge (button-style env) {:display "inline-block" :text-decoration "none"})) (defstyled button :button [env] (merge (button-style env) {:you-get "the-idea"})) I currently still have a base.css which includes normalizr.css and some other generic classes, you can of course still use (button {:className "generic"} ...). Nothing wrong with that. As for performance: The generated selectors are very specific in that they only match one thing, too open generic styles tend to cause issues. Also if you stick to "modern" things (flexbox) the need for some filler HTML elements goes away which improves overall performance, not just CSS. Style generation also happens ONCE, so even complex style-fns should not be an issue ever. Also thanks for :advanced optimizations the code to generate the CSS should by much smaller than any actual minified CSS. Did I mention dead code removal yet? ;) But I currently have only 89 "defstyled" things in my project myself, as this is still fairly new. Too early to make general claims about performance, but it should probably be on par with hand-written CSS. Generating styles on the client might be a bad idea too, my stuff is not yet complex enough to say. Time will tell, I am committed however as the past few weeks produced basically zero headaches about CSS and that is a nice feeling. /thomas -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
[ClojureScript] Re: CSS in CLJS
On Thursday, February 2, 2017 at 11:36:43 PM UTC+1, Thomas Heller wrote: > Hello, > > I'm not sure how many of you are in this horrible situation where you have to > write CSS for your React Components. I typically have to write way more than > I'd like and always hated the way I wrote it. Until a few weeks ago. > > I wrote this thing and so far I really like it. Too early to tell whether > this is actually a good idea but I already prefer it over pretty much > everything else I have used in the past (CSS, SCSS, OOCSS, BEM, ...). > > Anyways here it goes: > > (ns my.fancy.component > (:require [shadow.markup.css :as css :refer (defstyled)])) > > (defstyled title :h1 > [env] > {:color "red"}) > > (h1 {} "hello world") > > In Clojure this produces hello > world. There are also ways to generate the appropriate CSS so the > element is actually styled in your page. Not totally settled on the final API > but it works well enough for now. > > In ClojureScript this produces a ReactElement and should work with React > natively and most CLJS React Wrappers like OM (although I tried no other than > my own). No extra CSS generation is required here, just include it in your > page and it will be styled. > > More here: https://github.com/thheller/shadow/wiki/shadow.markup > > This is basically my take on the whole css-in-js thing that is happening in > the JS world if anyone follows this. I wasn't happy with any of their > implementations so I wrote this. > > If you'd like to use this try it with this: > > [thheller/shadow-client "1.0.180"] > > The Clojure part also requires hiccup, the CLJS parts require React via > cljsjs.react. > > If anyone is actually interested in this I'd be happy to go over some more > details. I just open-sourced this as I wanted to use it in another project > and needed a place to put it. Consider this very ALPHA though, you have been > warned. ;) > > Cheers, > /thomas This is interesting. A few thoughts... Have you considered using garden syntax for the style generation? I have a ton of garden styles already, and I imagine others do to, direct porting would be awesome. Is there a way to reuse css classes? Generating classes for each element potentially produces a lot of redundant css, and in cases where performance is an issue, the same class being applied to many elements will be faster -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.
Re: [ClojureScript] CSS in CLJS
I looked at garden but never used it. It seems like a direct alternative to SCSS/Less, but nothing more. The intent of shadow.markup (sorry, couldn't think of a better name yet) is that I basically never want to write a single selector ever again. There are several cases where this is still needed but way less than I usually do. You get several things for free by combining the actual HTML Tag with its CSS. This is a pretty good introduction to the topic of css-in-js and styled-components for React https://www.youtube.com/watch?v=19gqsBc_Cx0 My API is very much inspired by this library, although less strings and more Clojure. There are many more implementations of this here: https://github.com/search?q=topic%3Acss-in-js=Repositories Let me try with some sample Clojure code. You'd write something like this to generate a simple html snippet: (ns my.site (:require [hiccup.page :refer (html5)) (defn page-html [title body] (html5 [:head] [:body [:div.box [:h1.box__title "foo"] [:div.box__content body]]])) Here we invented tree css classnames that we need to remember here and whereever we get the actual CSS from. This over time leads to this: http://mrmrs.io/writing/2016/03/24/scalable-css/ at least it did for me in just about every project ever. Garden does not do anything in this regard I think, you still define things in two different places. With shadow.markup you do this: ;; put all defstyled elements in a separate namespace in a .cljc, so you can use it everywhere. (ns my.html.box (:require [shadow.markup.css :as css :refer (defstyled)])) (defstyled box :div [env] {:padding 10 :border "1px solid green"}) (defstyled title :h1 [env] {:color "red"}) (defstyled contents :div [env] {}) ;; my/site.clj (ns my.site (:require [my.html.box :as box] [hiccup.page :refer (html5)) (defn page-html [title body] (html5 [:head] [:body (box/box {} (box/title {} title) (box/contents {} body))) ])) You do not need to remember whether to use a :h1 or :div, you just directly use the elements. Since everything in CLJ(S) is namespaced we get a safe naming scheme for CSS classes for free as well. You just write normal CLJ(S) code, you don't need to context switch and synchronize the class names back and forth. Refactoring the defstyled name in Cursive will rename all of its uses as well the CSS classnames. The CLJS version with :advanced gives you dead code removal for free, so if you don't use an element it's CSS will be removed as well. There are many more things but the basic idea is to bundle the CSS with the HTML that uses it while still supporting all of CSS (ie. no inline styles) and remaining pure Clojure. HTH, /thomas -- Note that posts from new members are moderated - please be patient with your first post. --- You received this message because you are subscribed to the Google Groups "ClojureScript" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojurescript+unsubscr...@googlegroups.com. To post to this group, send email to clojurescript@googlegroups.com. Visit this group at https://groups.google.com/group/clojurescript.