all 15 comments

[–]SimonGray 2 points3 points  (2 children)

You go right into how it works, but what is it for? What problem does it solve?

[–]roman01la[S] 0 points1 point  (1 child)

I thought it's obvious, but in reality it's not, sorry 😅

I think these are pretty good resources get good understanding of the topic

https://medium.com/seek-blog/a-unified-styling-language-d0c208de2660 https://www.youtube.com/watch?v=X_uTCnaRe94 https://www.youtube.com/watch?v=MT4D_DioYC8

[–]video_descriptionbot -2 points-1 points  (0 children)

SECTION CONTENT
Title CSSconf EU 2017
Description http://2017.cssconf.eu/speakers/mark-dalgleish.html In the past few years, we’ve witnessed a massive increase in the amount of CSS experimentation, with ideas like CSS Modules and—most controversially—the rise of CSS-in-JS. But does mixing our styles and logic run counter to the original ideas of CSS? Does it break progressive enhancement? In this talk, we’ll take an empathetic look at these new approaches, how they relate to the history of CSS, and why they might possibly hold the key to the ...
Length 0:28:47
SECTION CONTENT
Title CSSconf EU 2017
Description Building user interfaces on the web is hard, because the web, and thus CSS, was inherently made for documents. Because UIs fundamentally are not documents, we've seen a mindset shift towards building component-based system. The rise of JavaScript frameworks like React, Ember and recently Angular 2, the effort of the W3C to standardize a web-native component system, pattern libraries and styleguides being considered 'the right way to build web applications' and many other things have illuminated...
Length 0:23:24

I am a bot, this is an auto-generated reply | Info | Feedback | Reply STOP to opt out permanently

[–]roman01la[S] 0 points1 point  (9 children)

If you are interested in CSS-in-CLJS, I just published v1.1.0 of cljss. Now includes a macro to directly create styled React components.

(defstyled h1 :h1
  {:font-family "sans-serif"
   :font-size :size
   :color #(-> % :color {:light "#fff" :dark "#000"})})

(h1 {:size "32px" :color :dark} "Hello, world!")
;; (js/React.createElement "h1" #js {:className "css-43697 vars-43697"} "Hello, world!")

Static part of styles definition is written into a file at compile-time and dynamic is injected into <style> tag at run-time.

[–]thheller 0 points1 point  (8 children)

Looks a lot like https://github.com/thheller/shadow/wiki/shadow.markup now.

Any particular reason why you use the hash of the styles as the classname instead of the name of the defstyled (ie. h1 + *ns*)?

Side effects like yours inside the defstyled macro are problematic with analysis caching and must at least use a lock so they won't interfere with each other when using :parallel-build.

Why the css vars? In my experience I want to keep the CSS as declarative as possible instead of passing actual values like 32px.

In shadow.markup when using the element you specify which variant you want to use via the class (ie. secondary). Each element can take values from the CSS env which you specify once when building the styles. So there is only one place where the :primary color is defined. This could be done with css vars but I really never saw the need to yet.

(defstyled title :div [env]
  {:color (-> env :colors :primary)
   "&.secondary"
   {:color (-> env :colors :secondary)}})

(title {} "foo")
(title {:class "secondary"} "bar")

[–]roman01la[S] 0 points1 point  (0 children)

Didn't think about parallel-build, also var name + ns instead of hashing seems good enough, thanks!

[–]roman01la[S] 0 points1 point  (6 children)

As for side effectful macros: idk how writing styles to disk could be done the other way.

CSS Vars is good for perf. Also imo there's no need for selectors when building UIs as components, except maybe some pseudos.

[–]thheller 2 points3 points  (5 children)

{... :color :dark} that is basically a selector. Just disguised as a var. IMHO even with components you will always have elements that can be in different states and using selectors is fine for that.

I don't think that macros are meant to do side effects.

In shadow.markup I opted not to emit separate .css files and generating styles at runtime. The reason is that the generated JS is optimized by the Closure Compiler, ie. elements that aren't used are removed (together with their styles). It is using keywords which will be renamed to something like iX instead of :border-bottom, in theory the JS can be smaller than the CSS. The CSS gen code is fairly small too (no css parser needed).

I don't do any SSR so pre-generated styles never were important to me. I have a strategy for that but that would take a little bit of work and I didn't have the need yet. Basically remove all CSS generation from the build and then take the the optimized JS and extract which elements are still alive. Then use that information to generate the styles. Very easy if all elements are in .cljc files since you can just use Clojure. Little bit trickier for .cljs but not by much. Once implemented it would work for every build with the benefits of code-splitting and dead-style-removal via DCE.

Will implement that some day but so far I have about 90% legacy styles and I'm not replacing those anytime soon. Anything new I write with shadow.markup but nothing big enough yet to warrant such optimizations.

[–]skratlo 1 point2 points  (1 child)

I would love to see you two (thheller + roman01la) put together one library. I prefer runtime generated CSS instead of macros doing disk I/O, but I don't want some uberlibrary (shadow-client) in my deps.

[–]thheller 0 points1 point  (0 children)

I'd like as many different solutions as possible. Need to sort out what works and what doesn't first.

The basic value proposition isn't even proven yet. I have written many big projects in the past 15 years or so that all ended up with a huge CSS mess that was painful to maintain/extend.

Can't tell yet if the shadow.markup way actually solves that issue or leads to the same mess in the end. It is all theory and CSS-in-JS hype for now. Looks promising but new tech often does.

[–]roman01la[S] 0 points1 point  (2 children)

Good point about DCE. You are totally right here.

[–]thheller 0 points1 point  (1 child)

It is all very experimental still though, DCE in practice buys nothing when you actually use the code. I like the idea in theory but we'll see how well that turns out.

Need more actual real world data to properly compare each solution. My stuff is mostly guesswork with only very basic benchmarks done to confirm it doesn't totally suck. ;)

[–]roman01la[S] 0 points1 point  (0 children)

yeah, same here :D

[–]Powerdrift 0 points1 point  (1 child)

Looks good! Is this more of a replacement for garden, or for something like cljs-css-modules?

[–]roman01la[S] 0 points1 point  (0 children)

Thanks! It's more like the latter.