

React: CSS in JS - insin
https://speakerdeck.com/vjeux/react-css-in-js

======
lobster_johnson
I'm not sure the implementation is quite what we need, but I definitely agree
with the rationale.

CSS is global, as they point out, and CSS makes assumptions that may not be
true today. For example, most apps these days — at least the kind I build –
gain zero benefit from separating the style from the DOM. We never, ever apply
different stylesheets to a single app.

The few use cases where truly separate stylesheets would be useful aren't
significant enough to justify the separation. For example, "themes" are
implemented through SASS variables that drive the presentation -- not with
separate stylesheets.

And generally speaking, apps are simply too complicated to reimplement the
entire app's stylesheet multiple times. And CSS cascading rules are
sufficiently gnarly (eg., the exactness of the selector guides priority,
except !important, etc.) to make things too error-prone to work in practice.

CSS was designed for basic marked-up hypertext documents, not today's sites or
single-page apps. It works fine for documents, but for everything else it's
increasingly showing an impedance mismatch, especially with respect to
isolation and layout handling. Even with "flexbox" it's very limited compared
to constraint solvers like Cassowary. We have to face the fact that layout
belongs to content.

Anyway, there are a few problems with the CSS-JS approach:

\- Media queries aren't possible anymore and must be done with JS. (I usually
end up doing a lot of this in JS anyway, because media queries only deal with
viewport sizes, not parent container sizes, so media queries break component
isolation.)

\- When you have styles applied to almost every element in a complex
component, the DOM will look increasingly messy. You can't do mass-application
things like "div > li { ... }".

\- It's going to massively increase DOM size.

\- Surely browsers must have highly optimzied CSS processors these days. I
can't help but think that applying entire style rules to DOM elements must be
slower than just referencing an existing compiled style.

Personally, I suspect a better way to approach this would be a React-specific,
component-oriented style language. Not the modest tweaks they demonstrate in
the first slides, but something built from the ground up.

------
Ronsenshi
At the last slide author says that the goal of that talk was to convince us to
drop CSS and use JS.

Can't say that those slides were very convincing. Right now it looks way too
overengineered.

I'm not a fan of muddying JS with bits of HTML in general, and now CSS in JS?

Yes, that may work for Facebook. They've been inventing their own way of doing
things for a while now, but I very much hope that won't go beyond Facebook.

~~~
bastawhiz
I agree. CSS is global, but that doesn't mean that it can't be managed. I
think going down the road of having programmatically generated stylesheets is
solving a relatively small problem with an extremely over-engineered solution.
Soon enough, you can't actually develop without the use of dozens of different
tools for generating source maps, transpiling, etc. In all honesty, any
presentation that says "If I started with this, you would have written me off
as crazy" is probably giving itself too much credit and is in fact based on
crazy.

The whole "button in an overlay" section of the presentation shows just how
mind-bending this becomes. In a sane universe, one simply needs to write
`.overlay .button`. But of course, you can't do that with CSS that's
referenceable from a single name (or where you're statically applying styles
to an element rather than letting the CSS...well...cascade). I could see if
the solution presented made me say "Oh, this is a much more intuitive way of
styling a web application." It didn't. Instead, I read, "We have this crazy
proprietary namespaced CSS system that has limitations that we can't work
around without building an even crazier system on top of it," and thought to
myself, "Well don't do that then."

So now you're at a point where everything is an inline style. Your browser's
devtools are essentially useless because you can't see how the CSS cascades.
What overrode what? God only knows, go look at the JavaScript.

Of the seven problems outlined at the beginning, I think few of them were
really a problem to begin with. A codebase that 1. properly organizes its CSS
into files with descriptive names and a sane directory structure 2. uses OOCSS
or other best practices 3. is mindful of style bloat 4. has a sane DOM
structure and 5. uses a preprocessor of some variety for variables does not
suffer greatly from any one of those issues. I work on a codebase of >10^5
lines of CSS that minify+gzip down to 30kb. That's a single small JPEG worth
of code.

I would be interested to see some of the alternative solutions that Facebook
explored that don't dive straight into the Twilight Zone.

~~~
lobster_johnson
We organize our SASS files very carefully. One file per component, careful
naming, strict rules about overriding a component's internal classes
(".mycontainer .somecomponent .somecomponent_title" is illegal). It's still
painful.

One reason is cascading. The way CSS applies to trees means that every
component has to be aware of what properties it could accidentally inherit. So
to code defensively, you override things like colors and fonts. Using SASS
mixins helps.

But sometimes you do want contextual modifiers, for example styling all
components differently when they're in a certain type of container. For
example, if the container's background is light grey, we'll want all nested
text to have a subtle bevel (ie., white text-shadow).

It's tempting to use cascading for this, but that breaks — by definition! —
separation of concerns. In one way it's better to actually have each component
be container-aware; for example, given that Form and SpecialContainer are both
components you can do this in form.scss:

    
    
        .SpecialContainer {
          background: #f0f0f0;
        }
    
        .Form {
          .SpecialContainer & {
            text-shadow: 0 1px 0 #fff;
          }
        }
    

It's cheating, though; now you have a dependency between the Form and
SpecialContainer that really wasn't needed. So when I'm not being lazy, I
resort to explicit parameters:

    
    
        .Form {
          &[data-light-background="true"] {
            text-shadow: 0 1px 0 #fff;
          }
        }
    

Now I have to pass "lightBackground" as a prop to the component have it set
the data-light-background attribute. Of course, this only works the component
embedding Form actually knows that it has a light background or is embedded in
one that has a light background. Not ideal.

------
stu_k
I can see that this approach might be viewed with a lot of suspicion, but this
gels with a lot of problems we saw while building the MontageJS framework.

CSS _is_ global, and it is a big problem to manage while building a large web
app (which of course Facebook is). I think everyone building a large site or
app has come across a bug where a CSS rule is unintentionally overriding
another. They are a pain to track down and almost impossible to prevent.

I haven't played with this approach (as it was only talked about today!) but I
think it's on the right track. The only thing I would like to see is the "CSS"
put into its own module and required into the component JS file. Not only
would this maintain the separation of style and markup, but also make it more
approachable for those CSS experts coming from the current way of doing
things.

I'm really looking forward to seeing how this progresses.

