[HN Gopher] Show HN: Compiled, buildtime atomic CSS in JavaScrip...
       ___________________________________________________________________
        
       Show HN: Compiled, buildtime atomic CSS in JavaScript and all your
       favorite APIs
        
       Author : madou
       Score  : 47 points
       Date   : 2021-01-02 06:49 UTC (16 hours ago)
        
 (HTM) web link (compiledcssinjs.com)
 (TXT) w3m dump (compiledcssinjs.com)
        
       | austinjp wrote:
       | Personally I'm a fan of cxs [0] which is (or purports to be)
       | atomic among other strengths. From the readme:                 -
       | 0.7 KB (gzipped)       - Zero dependencies       - High
       | performance ("fast af")       - Deduplicates repeated styles
       | - Dead-code elimination       - Media queries and pseudoclasses
       | supported
       | 
       | Works with any framework or with none, apparently, although I've
       | only used it with Preact. Supports themes. Everything I need and
       | nothing I don't.
       | 
       | [0] https://github.com/cxs-css/cxs
        
         | jitl wrote:
         | I think csx is probably the best choice amongst the compute-
         | styles-at-runtime CSS-in-JS libraries. The brutal simplicity
         | has a lot to offer. For most projects csx is perfectly fine.
         | However it can't beat a more complex zero-runtime precompiled
         | styles system on paper -- but it's an optimization tradeoff you
         | could choose if you need it in the future.
        
       | [deleted]
        
       | pestatije wrote:
       | What was wrong again with runtime CSS? By the smell of it seems
       | to be performance, so: can somebody point to performance
       | comparisons, or give a brief of the advantages?
        
         | mStreamTeam wrote:
         | There's nothing wrong with runtime CSS. Frontend devs just like
         | to come up with elaborate solutions to problems that don't
         | exist
        
           | simonmales wrote:
           | From my understanding of frontend performance, JS parsing is
           | blocking.
           | 
           | So reducing the JS "load" is a performance win on the client.
        
         | jitl wrote:
         | It's all about time to interactive.
         | 
         | For a big complex app (eg, https://www.notion.so which I work
         | on), a significant fraction of JS code size is spent describing
         | styles. There can also be JS cycles spent doing color math like
         | lighten, darken, hue shifting on base colors, etc. With runtime
         | CSS-in-JS, all of that style JS code must be parsed and
         | executed by the JS runtime _on every page load_ by _every
         | user_. That's a lot of CPU time and user wait time multiplied
         | out.
         | 
         | Zero-runtime improves page load performance by moving this
         | extra code from the JS vm to static CSS files. The majority of
         | style computation happens at build time. The CSS can then be
         | downloaded and parsed _in parallel_ with the JS (woo threads?).
         | The separation _may_ improve caching compared to all-JS
         | solution as well, depending on how granular the CSS and JS
         | output files are.
        
       | pii wrote:
       | hamburger emoji for a menu icon is for sure an underused design
       | pattern
        
         | barbarbar wrote:
         | Indeed. But it will take of now. Everybody wants to click that
         | delicious hamburger.
        
       | fastball wrote:
       | Doesn't @emotion's babel plugin already do this, or am I missing
       | something?
        
         | lf-non wrote:
         | Not quite. Emotion doesn't do the atomic splitting - ie. one
         | class name per style rule. This splitting results in ugly
         | looking HTML but if two components are using some common subset
         | of CSS rules they will partially reuse the same css classes.
         | 
         | It is closer to https://www.styletron.org/ in that regard.
        
       | niksmac wrote:
       | Isn't this the same as Styletron is doing?
       | https://www.styletron.org
        
         | jitl wrote:
         | Styletron create "atomic" (single property) CSS classes as your
         | application runs in production because it has no macro,
         | compiler, or bundled plugin. "Build-time" means the CSS is
         | somehow extracted from the JS files and inserted into HTML or
         | static CSS files during the bundling process, so that the JS to
         | compute the styles never runs on the client/production. There's
         | only whatever code is needed to add the generated class names
         | to the DOM nodes created by React (etc) when the app runs.
        
       | [deleted]
        
       | jitl wrote:
       | The differentiating feature of Atlassian's @compiled package is
       | not the "build time atomic css" - it's that you can distribute
       | components that use @compiled on NPM without requiring your
       | consumer to futz with Webpack include paths for e.g. CSS files.
       | Do I have that right? @madou is the extraction shipping yet? The
       | docs have a few places that say "coming in 2021" - what's the
       | status?
       | 
       | For those interested in build-time CSS in JS, also called Zero-
       | runtime CSS in JS, you might also want to check out:
       | 
       | - Linaria (https://github.com/callstack/linaria) I use on my
       | personal site. I ran into trouble/bugs trying to integrate it
       | with Notion's build process; the Webpack/babel bits are very
       | brittle.
       | 
       | - Treat requires that you write the JS that computes your styles
       | in esperare xxx.treat.js files which is annoying from my point of
       | view - I want single file components. (https://seek-
       | oss.github.io/treat/)
       | 
       | - No idea about this one, but it's more recent. Has some other
       | interesting things in the inspiration section of the README
       | https://github.com/CraigCav/css-zero
        
         | nwienert wrote:
         | I've been working on one that runs on top of React Native Web.
         | Compiles to atomic CSS on web, and StyleSheet on native.
         | 
         | It marries in-line style props (like JSXStyle) with SwiftUI
         | style stack views.
         | 
         | It's very much alpha, on my GitHub.
        
         | have_faith wrote:
         | Have also been using Linaria on a side project recently,
         | enjoying it a lot so far. I skipped most of the other css-in-js
         | solutions when I saw they where using runtime js to manipulate
         | styling which intuitively just feels unnecessary for 99% of the
         | pages style. Very happy with Linaria so far.
        
       | [deleted]
        
       | crituquie wrote:
       | why? css exists because one shoud not need js just for styling!
       | js is dangerous for me!
        
       | mouzogu wrote:
       | why is there such a prevalence of mawkish phraseology in the
       | javascript community...
       | 
       | i was reading the landing page for a js library and it said
       | something like "battery-pack included", makes me feel kind
       | sick....or maybe i'm just a grumpy sod
        
         | iaml wrote:
         | "Batteries included" was invented by rails folks IIRC.
        
       | iddan wrote:
       | I was building a similar solution 4 years ago [1] but got stuck
       | with integration to Webpack. I'm very glad someone succeeded to
       | do so. [1]: https://github.com/iddan/stylesheet
        
       | christophilus wrote:
       | There are already quite a few alternatives in the comments, but
       | I'll just add that I have really come around to the Tailwind way
       | of doing this. On my current project, I haven't had to write much
       | CSS at all other than a handful of animations, and it all looks
       | consistent and custom. It's a breath of fresh air.
        
       | Traubenfuchs wrote:
       | Could someone please explain the following line to me?
       | 
       | export const Button = styled.button``;
       | 
       | Why is there a string right after the field "button" of the
       | object "styled"? How is this valid JS? What does it do?
        
         | lucideer wrote:
         | I don't know why that space is there, it could be accidental or
         | a deliberate stylistic quirk of the author, but it seems
         | harmless (if not idiomatic).
         | 
         | > _How is this valid JS? What does it do?_
         | 
         | I'm curious if Python (or a similar whitespace-sensitive
         | syntax) is your first/familiar programming language.
         | 
         | The extra whitespace here does nothing.
         | 
         | The semicolon in JS is an (optional) expression separator,
         | similar to in Bash/Shell. It can occur at the end of a line or
         | at the beginning of a line, or in between lines. Or in between
         | two expressions on a single line. Any whitespace chars before
         | or after it are irrelevant/ignored.
        
         | commotionfever wrote:
         | checkout javascript "template literal tags"
         | 
         | https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
        
         | [deleted]
        
       | tobr wrote:
       | Yet another case of documentation saying "JS" when they mean
       | "React, specifically". Every single example I can see here uses
       | React, but if this deserves the CSS-in-JS moniker, please give at
       | least one example of usage with vanilla JS. It's like peak jQuery
       | all over again.
        
         | ljm wrote:
         | We're probably at that point again where a developer 'knows'
         | React but will completely flounder when faced with anything
         | outside of that ecosystem. Same with jQuery, same with Rails
         | and Ruby.
        
           | RobertKerans wrote:
           | I've started seeing this quite a lot recently when working
           | with beginners. Worst one recently was someone who had
           | extreme difficulty understanding how to make different web
           | pages using only HTML, but much more mild versions of this
           | have been cropping up in frequently for me over the last
           | year.
        
           | bryanrasmussen wrote:
           | Since JavaScript evolved to incorporate many of the APIs that
           | jQuery pioneered at some point knowing only jQuery was not
           | such a problem.
           | 
           | But even before this evolution much of jQuery was just sugar
           | to make cross-browser problems manageable.
           | 
           | I am not actually aware, I think, of any developer that just
           | knows React but if they exist I suspect they would have an
           | even harder time of it when deprived of their favored
           | framework than those developers back in the day that just
           | knew jQuery.
        
             | austincheney wrote:
             | Query selectors likely came from jQuery's Sizzle engine,
             | but most of the jQuery APIs, all methods, were never
             | adopted. The best I can think of that did get adopted is
             | _closest_ which uses a query selector to find a matching
             | ancestor node.
             | 
             | The reason why most of the jQuery approach is not adopted
             | is because it is so incredibly slow. First you have to
             | consider that query selectors, at their best performance
             | (Google Chrome), are about 460x slow than the old DOM
             | methods. All the jQuery approaches would be slowness that
             | multiplies on top of the already slow query selectors. In
             | Firefox query selectors are about 10,000x to 250,000x
             | slower than the standard DOM methods.
             | 
             | From a standards perspective there is no incentive to go
             | down that path as it cripples the interface it describes.
        
           | jokethrowaway wrote:
           | I see it all the time.
           | 
           | Tons of developers coming out of bootcamps (and even a few
           | designers with no coding experience) who know how to string
           | together a few react components but have problems with basic
           | JS.
           | 
           | It's not necessarily bad, it's just higher level coding.
           | What's bad is when these people get hired as engineers.
        
       | swiley wrote:
       | So you took something written in a regular grammar and made it
       | into the same thing except with a very complex context free
       | grammar with support for recursion?
       | 
       | I hate to be a grumpy puss but using this sounds like a step
       | backwards.
        
         | jitl wrote:
         | Well, in the long run we've learned that maintaining a large
         | and complex UI's CSS by hand is very tedious and error-prone. A
         | miss configured style that, for example, makes the Airbnb "Book
         | It" unreadable for some % of the population can lose millions
         | of dollars, but never throw a stack trace.
         | 
         | So, engineers working on UI toolkits often reach for CSS code
         | generation to ease maintenance. At first it was all PHP
         | templates. Then it was Sass (206), is a popular purpose-built
         | language for generating CSS which saw a lot of use in the Rails
         | community. Sass is very good at its job because it handles a
         | lot of CSS niceties in nice ways, but it's a lot of extremely
         | domain specific complexity. A whole new Turing-complete
         | language _JUST_ for CSS? Not ideal.
         | 
         | The next step is to move all the UI definition into a single
         | place, i using a single language that abstracts the underlying
         | HTML/CSS/JS files & semantics. We do that by writing JS, and
         | having a compiler program extract the CSS bits. This gets us
         | ideal performance & ideal maintainability at the cost of build
         | complexity. This is a worth while trade, because in the long
         | run the compiler will get so good that the cost becomes
         | minimal; compare to other ecosystems, for example the Kotlin
         | compiler is quite complex, but I never think about x86 assembly
         | when writing Kotlin.
        
           | rualca wrote:
           | > The next step is to move all the UI definition into a
           | single place, i using a single language that abstracts the
           | underlying HTML/CSS/JS files & semantics.
           | 
           | That sounds like a gigantic step backwards, and one which
           | does not follow the example you've mentioned.
           | 
           | The point of Sass was to introduce backwards-incompatible
           | changes to CSS which adds nice human-readable syntactic sugar
           | to CSS. Being turing-complete is besides the point and even
           | it's regular use. In fact, I worked in projects where Sass
           | was introduced just for it's support for nesting and partials
           | alone.
           | 
           | Mixing content and presentation in scripts misses any of the
           | lessons from the last couple of decades. It feels like yet
           | another example of the cargo cult of javascript, where people
           | mindlessly argue that dragging everything into a script
           | solves anything at all.
        
             | ratww wrote:
             | _> Mixing content and presentation in scripts misses any of
             | the lessons from the last couple of decades_
             | 
             | If you're using React or Vue, chances are your content is
             | coming from JSON in fetch requests, etc, not from the
             | HTML/JSX in your components. In those cases _HTML /JSX is
             | the presentation_. The content/presentation separation
             | still exists.
        
             | mattlondon wrote:
             | > Mixing content and presentation in scripts misses any of
             | the lessons from the last couple of decades.
             | 
             | Agreed - although this is not a JavaScript thing, but a
             | react thing I think (maybe also Vue? No idea about that).
             | E.g. Angular still has CSS (actually SASS) and HTML in
             | separate dedicated files, and then a another separate file
             | that contains the JavaScript (actually typescript) for the
             | logic itself.
             | 
             | I do not see the benefit _at all_ of putting all these
             | things in one single file, apart from trivial tiny simple
             | things (angular allows you to create single-file components
             | for instance) or for making  "To-Do with React" type
             | tutorials look easy. Once you get more than 100-200 lines
             | of code + html + CSS then it is time to separate the files.
        
               | jitl wrote:
               | I would rather have my files be Page.component,
               | Header.component, Details.component, Article.component
               | than have my three files be Page.html, Page.css, Page.js.
               | 
               | What is the benefit of separating code by file type? If
               | your reasoning is to reduce coupling, I think this is
               | false simplification - again, in complex applications
               | with lots of interaction, there is no escaping the
               | coupling of DOM nodes, JS logic, and styles. Any feature
               | changes change is going to need to modify all three.
               | Maybe for a mostly read-only site de-coupling these
               | things makes sense, and you can achieve your goals with
               | something like Bootstrap, where you compose a bunch of
               | reusable CSS classes. But for the majority of work I've
               | done over the last 8 years, that decoupling model doesn't
               | work. It's an even harder nest of snakes when you
               | multiply 3 screen sizes x 2 input methods x N pages where
               | CSS could be used - again for something simple, it's fine
               | to just collapse columns on mobile (the typical CSS
               | column-css-6 style) but frequently you want this stuff to
               | be much more responsive to user device and input than
               | decoupled styles allows.
        
               | rualca wrote:
               | > I would rather have my files be Page.component,
               | Header.component, Details.component, Article.component
               | than have my three files be Page.html, Page.css, Page.js.
               | 
               | ...except that Page.css at most only adds minor tweaks
               | that cascade over the site's styling, and arguably
               | already should be a part of the site's main styling
               | definitions.
               | 
               | > What is the benefit of separating code by file type?
               | 
               | Separation of concerns. This lesson was learned the hard
               | way. Must we keep on relearning it?
               | 
               | > I think this is false simplification - again, in
               | complex applications with lots of interaction, there is
               | no escaping the coupling of DOM nodes, JS logic, and
               | styles.
               | 
               | This assertion is quite wrong and misguided. Styling is a
               | property of a site's visual identity. It is not a
               | property of a component or a specific interaction state.
               | Any well-designed site follows a uniform visual identity
               | which spans over all aspects pertaining to user
               | interactions. Moreover, UI components are also uniform
               | and reused. There is no excuse.
        
               | robertoandred wrote:
               | React doesn't require mixing styles and content. You can
               | use regular CSS files just fine.
        
           | jokethrowaway wrote:
           | Then you go back to HTML with attributes to control style,
           | which is where we were before CSS.
           | 
           | It's good to have a level of separation between style and
           | content. The problem with HTML and CSS is that often times
           | you need to change your HTML to change the style of your
           | application.
           | 
           | This is because HTML+CSS was meant to be for documents. It
           | took ages to evolve into what we have today and it still has
           | a lot of baggage. Designing apps with it is a hack which
           | became mainstream.
           | 
           | If we want to improve the situation, I think we need a couple
           | of standards to define application content and application
           | style which can be compiled to HTML + CSS (as browsers are
           | probably going to stay around for a bit longer).
           | 
           | Component based libraries (like react) are well placed to do
           | something like this and it would help developers faced with
           | this uneven separation of style, content and markup.
        
             | jitl wrote:
             | I view the current Cambrian explosion of CSS-in-JS
             | approaches as a distributed search for the "new standard".
             | Better to have 1000s of developers working on the problem
             | then have 6 people on a committee make another bad, short-
             | sited standard that becomes "cruft" in 4 years.
             | 
             | If you views React's JSX as the "content" part of
             | content/style break, then we're not too far off. It
             | compiles down to HTML :)
        
       ___________________________________________________________________
       (page generated 2021-01-02 23:02 UTC)