

Fix CSS by writing it in JavaScript - oleg009
http://slides.com/kof/jss

======
talmand
I'm sorry but I totally fail to see the problem that this is supposedly trying
to fix.

In the example provided, the problem is presented as a failure of cascading in
CSS. But the problem as I see it, is in the structure of the HTML. The example
is a component with a button inside a component with a button. Then global
selectors are used which creates a result we don't want.

Slide 11 states global selectors are a problem. Which they can be, if used
improperly just like every other tool we have access to.

So, the solution is to write Javascript that results in using classes. Which
is what should have been done in the first place.

So, instead of creating a proper class structure in the HTML it is suggested
to use Javascript to create classes, inject style sheets into the dom, and
inject classes into the HTML elements on page load?

All to avoid using CSS properly?

I'm sure this is a wonderfully coded project, has interesting ideas, and may
be useful to some, but as a front-end developer I seriously doubt I would ever
use this nor recommend it. I would suggest just learning CSS, it's not that
hard.

I would say that this type of project would be far more suited for a back-end
library that generates stylesheets on the fly in an effort to maintain code
efficiency. But doing all this in Javascript just seems to be about addressing
people's attitude towards CSS and not about actual problems in CSS.

~~~
spion
How does one properly use classes without making them global? Its either
global or tied to your document hierarchy. And tied to a hierarchy is worse
because it makes it harder to reuse a class outside that particular hierarchy
without modifying the original selector...

~~~
Sakes
The answer is LESS or SASS but for the love of god NOT JS. If you are
concerned with breaking cascading then...

.default-button(){ // properties }

.component-a button { background-color: red; }

.component-b button { .default-button(); color: green; }

~~~
spion
.default-button is still global in that example and may be accidentally
overridden by someone working on another part of the site.

~~~
talmand
Which is actually quite true, but that problem lies with the person who
overwrites the properties. That is not a problem in CSS. The most I would say
that the HTML structure and CSS classes was not properly planned out to help
prevent such things.

It can be done, it's just most examples of this type of thing is more along
the lines of "I want to do it my way!", which is not always a proper way to go
about things.

~~~
spion
Its definitely not a problem with the person. That person may be working on a,
say, date picker component (or something equivalent that is not yet covered
with HTLM5) that provides minimal styling (with the ability to override it).
They don't even know all their end-users.

They decided to use the name `.calendar`. Was that safe? Nope, their user #3
had an "upcoming events" calendar using the same class name that totally
breaks when the datepicker CSS is included on the page. Should they make sure
to prefix all their class names with their name? What if someone else with the
same name also decides to do this? What if they make a new alternate
datepicker, must they add the version number/descriptor too?

This is probably one of the reasons why we don't yet have separate reusable
components with minimal overridable styles for the web (instead we have only
entire pre-styled frameworks)

If styles had scope and HTML had a way to import them, we could say `import
calendar from "path/to/file"`, then use the calendar style on our component
and be sure that there is no way its going to leak outside of outside its
lexical scope. Web components will fix this (html imports, scoped
stylesheets). But web components aren't ready yet.

Let me ask you a different question though: is there a reason for the "oh god,
not JS" sentiment? The solution is potentially even simpler than CSS: styles
are defined as variables containing JSON objects, they're exported as a
module, and can be imported and used by any component and mixed freely. No
cascading/selector rules, no priorities, no overrides. When HTML CSS and JS
share scope, things become much simpler.

~~~
talmand
Your example only shows to me problems in the person and/or the team doing the
CSS coding. It is certainly possible to namespace CSS if guidelines are
established at project start, just like with coding any other language. What
happens if two developers namespace their class in the same way?

The reason I would say no to a JS solution is simply because you are adding
yet another step to the render of the page, more code for the browser to
parse, and in the end results in the same issues you started with as they are
only masked. This is just an attempt to make something work in a fashion it
was designed to do. I'd rather fix the problem at the source instead of adding
another layer to the problems.

But in the end, no matter what fancy JS code that comes up it still has to
render out the CSS exactly as the browser expects it to be. That means that
whatever this thing generates, people who know CSS can hand-code the exact
same thing. Any problems that exists for CSS exists in this as well, it just
masked so it's not readily apparent.

~~~
spion
But what if there isn't a single cohesive team developing the website? There
are no globally established practices for CSS name-spacing and there are
multiple ways to do it (based on what tradeoffs you're willing to make).

See font-awesome for an example of what I mean by library (yes, they prefix
everything with `fa-` which is fine until the bootstrap team comes up with a
FizzActivity widget in bootstrap, which you wont be able to use together with
fontawesome)

What happens if two developers namespace their class in the same way in JS?
Well, with CommonJS this is pretty much impossible (import by path), and even
without CommonJS there is no incentive to do it as you can easily pick a huge
namespace without it affecting anyone. Just adding `var shortName =
long.namespace.containing.shortName;` fixes the long name without that short
name having effects anywhere else in the code or any of the inner functions
(components) you may call, because... lexical scope.

And sure, we can hand-code everything in assembly too - after all thats what
compilers do anyway. But that doesn't mean that the higher level language has
all the problems that assembly has. A tool like this can do a lot of the job
for you, by generating unique names and letting you refer to them via any
(variable) name you like.

------
lhorie
vjeux (of React fame) gave a presentation on a similar system they were using
at Facebook [https://speakerdeck.com/vjeux/react-css-in-
js](https://speakerdeck.com/vjeux/react-css-in-js)

"This-is-not-what-I-am-used-to" objections notwithstanding, it's certainly an
interesting approach to solve some CSS issues.

------
jacobr
Nice project!

The Cascade in CSS can be a real maintenance nightmare, and people seem to
have very different ideas on how to handle encapsulation and modularization.

After a while with React, I thought it would be nice to define all styles for
a component in the same location (inside my Component JavaScript). Setting the
`top` property of a popup in JavaScript, but `width` or whatever in a CSS file
just feels weird.

There's been some discussion about making this easier in React[1], but also
resistance, so while waiting I wrote my own little library[2] (not React-
specific), but it's not as feature rich as JSS.

I think that the fact that many projects[3] like this are popping up is
validating the idea.

    
    
      [1] https://github.com/reactjs/react-future/blob/master/04%20-%20Layout/04%20-%20Inline%20Styles.md
      [2] https://github.com/jacobrask/marcssist
      [3] https://github.com/js-next/react-style
          https://github.com/tenphi/jcss
          https://github.com/chenglou/RCSS

~~~
colinramsay
You can set top in CSS.

~~~
lhorie
He means "top" as in "top-relative-to-scroll-position-when-the-modal-is-
taller-than-the-screen-in-IE8"

~~~
colinramsay
Ah, well you'd still need something more powerful for that kind of thing to
work. A constraints engine for example:

[http://gridstylesheets.org/](http://gridstylesheets.org/)

If you're going to go to the trouble of writing a CSS processor, you could at
least add in some really interesting ideas.

------
JelteF
Why would you ever use this instead of an easier preprocessor like sass or
less?

~~~
jhpriestley
Javascript has superior facilities for scoping, abstraction, and calculation.

Sharing a single scoping system between JS, HTML and CSS removes the need for
global symbols (classnames or ids) to link the two together.

Abstractions in preprocessors are implemented by means of macros, and can lead
to large file sizes.

~~~
talmand
I'm sorry, but there will always be a need for classnames and ids for multiple
reasons. A tool like this doesn't remove them from being used, it just partly
removes them from the initial code.

Proper usage of CSS preprocessors will result in much the same code that this
tool will generate. Because in the end they both generate the same CSS.

~~~
boucher
That's not really the case. For one, it's incredibly easy to end up with very
bloated CSS files if you use something like less/sass. But more importantly,
those tools don't give you actual scoping.

Although it's not necessarily the main way the author is suggesting
interacting with this library, it can be used as a tool to apply inline styles
directly to elements, which gives you total control over the scope of your
styles.

~~~
talmand
If not done properly, anything code-related can result in bloated and
inefficient code. I fail to see how introducing Javascript code that requires
DOM manipulation is more efficient than a properly built style sheet.
Injecting styles inline to elements is an even more inefficient way of doing
things, you're likely to cause repaints all over the place during initial
rendering.

As I said elsewhere, if this were a system done on the back-end (or even in
something like Grunt) so that it was part of a compiling process then it would
have merit. But from what I'm seeing this appears to run only on the client
side which I feel is a bad idea.

------
chenglou
The few past submissions on writing CSS in JS didn't seem to have picked up
discussions. I'm glad this one at least does.

I'm gonna go ahead and avoid repeating what's already mentioned in vjeux's
presentation ([https://speakerdeck.com/vjeux/react-css-in-
js](https://speakerdeck.com/vjeux/react-css-in-js)). Instead I'll focus on
defending against the common "shortfalls" people tend to immediately point out
with this approach.

Designers will be uncomfortable with learning this: React's JSX has shown that
(surprise surprise) designers can bear modifying markup with a little bit of
code mingled in it. In this case, JS objects in their simplest form map very
well to css declarations. I don't believe designers will be scared away by
this at all.

"Atwood's law", "we already have CSS", "stop reinventing CSS": no one's
reinventing the _idea_ of CSS; we're reinventing the implementation of it.
Declaratively specify your layout is really nice, but you do want the backing
of a real language to do so. Merging two styles is just a `merge()`,
Overriding a style is just `bla.color = newColor` (assuming you don't mind the
mutation; otherwise clone it or use persistent collections), and (!) reusing,
importing, exporting styles is already solved with commonJS since you're
working with normal js objects.

We already have preprocessors: except preprocessors are there to solve the
exact problem "CSS in JS" is solving. The difference is that the latter,
again, uses a real, familiar language instead of inventing an ad-hoc new
syntax like we've done countless times with HTML templates. And since
preprocessors need to generate the final CSS beforehand, this limits lots of
potentials such as looping more than, like, ten times.

On this last point, I hope that none of the critics here used React's virtual
DOM before; If you did, and are still complaining about writing CSS in JS,
then you should go back and re-learn why the virtual DOM came to be. CSS in JS
is the "virtual styling" equivalent for CSS. The potentials are huge (runtime
feature detection for example). And this new layer allows us to map the neat,
declarative style to something else than CSS: say, webGL. This is _platform-
independent_ ; if anything, it's a nice conceptual model.

(Disclaimer: I made
[https://github.com/chenglou/RCSS](https://github.com/chenglou/RCSS))

~~~
oleg009
Thanks Cheng, you nailed it. Jss was actually inspired by your RCSS idea, I
just wanted a different implementation. So thank you again.

Some people here assume that I am stupid and didn't learn the css basics. This
is just funny.

~~~
chenglou
Glad you did! I'm not entirely satisfied with my API but the idea's there, so
very cool to see someone make something better out of it.

These kind of things will receive lots of oppositions at first, but once you
know the basics are right (e.g. trivial mapping from js obj to css) and build
on top of it, this is bound to take off one day like JSX did =).

~~~
malandrew
I don't get JSX, especially now that 0.12 requires you to use createFactory (a
big improvement over the old API) to encapsulate all the static JSX parts.
With JSX, you're losing all the things that make having a proper programming
language useful.

Have you given react-hyperscript a chance? [https://github.com/mlmorg/react-
hyperscript](https://github.com/mlmorg/react-hyperscript)

Having first class functions for creating DOM makes it much easier to keep
your DOM state creation dry. It's more tedious if you use it just like JSX,
but if you recognize where you are repeating yourself over and over again,
it's trivially easy to write functions that encapsulate all the repetitive
structures in your HTML.

Furthermore, you don't completely break all the tools out there like eslint
and whatnot. The h-script blends really nicely with solutions like RCSS and
JSS.

~~~
danabramov
Linting has not been an issue for a looong time since you can just lint the
output of the transform. And designers love JSX, and having designers feel
confident working directly on components saves huge amount of time.

------
ttty
Amazing (: I like the '&:hover': { part. Take a look at rcss
[https://github.com/chenglou/RCSS](https://github.com/chenglou/RCSS) Your lib
would be amazing to work with react.js. You would need to create the class
names based on the contents instead of incrementing an id to make server side
rendering faster. Take a look at rcss on how they do it.

------
colinramsay
Atwood's Law [1] kicking in here.... "Any application that can be written in
JavaScript, will eventually be written in JavaScript".

[1] [http://blog.codinghorror.com/the-principle-of-least-
power/](http://blog.codinghorror.com/the-principle-of-least-power/)

------
factorialboy
Question: Much of the CSS may not be written by programmers. How would we make
use of JSS in this case?

~~~
oleg009
jss not harder than less/sass/stylus ... its declarative json syntax most of
the time.

------
ttty
This reminds me of
[https://github.com/chenglou/RCSS](https://github.com/chenglou/RCSS) . It can
be used with react.js and it just works ok.

------
zajd
Pretty sure LESS/SASS already "fixed" CSS.

------
ArtDev
Use Javascript for CSS.. to process it out of LESS.

LESS is Javascript but with certain limitations. If you don't like it, write
your own. Or better yet, contribute.

------
semasad
Ok, he can be talking seriously. The problem he try to fix is easily fixed
with ANY CSS preprocessor, Stylus, Less, Sass...

------
rquantz
You know what I've never thought? "The problem with CSS is that it is not
imperative enough."

------
ArtDev
I only got a few slides in before it became obvious that he doesn't know CSS.

------
eridal
Now this is an interesting approach! Are there anyone using it in the wild?

------
mrcwinn
No.

------
imanaccount247
"Fix toothpaste by making it out of feces"

------
norcimo5
Hell yes!

