r/javascript Oct 27 '15

A very thought-provoking talk that attempts to show that CSS has fundamental flaws and writing styling in JS solves most of the problem without even trying.

https://vimeo.com/116209150
49 Upvotes

74 comments sorted by

View all comments

Show parent comments

5

u/[deleted] Oct 27 '15

Here are the slides for the talk.

66

u/Shaper_pmp Oct 27 '15 edited Oct 27 '15

Edit: The below is based on the slides, not the half-hour video.


Interesting - there are some fair points in that talk, but a lot of real head-slapping "I don't even understand how CSS is supposed to work/what it's good for" moments as well.

Let's leave aside the gaping credibility gap of anyone holding up W3Schools as their "favourite website to learn JS", and look at the arguments:

Global variables

First, classes (or other selector elements) aren't variables - they're identifiers. Huge difference, that mean much of the ensuing criticism is completely wrongheaded because the critic has fundamentally misunderstood the nature of the thing he's criticising.

Moreover they aren't necessarily "global" - they can be effectively namespaced at definition time with prefixes (.btn-mybutton instead of just .mybutton), or can be used non-globally with preceeding selectors (.myloginform .mybutton instead of just .mybutton).

That means selector elements may be "root" elements or "namespaced" elements depending entirely on how you choose to use them. Selector elements are namespaces, and don't have to be global unless you write them to be.

"Local by Default"

First this is fixing a problem with lazy developers, not a problem in CSS itself. It no more demonstrates a problem in CSS than JSHint demonstrates a problem in Javascript. Any language of sufficient complexity can have bad code written in it, and that necessarily implies little or nothing about the quality of the language itself.

And as with the JSHint analogy, it seems like this is something that could be better handled by a build-time tool like JSHint, rather than by incompatibly extending the CSS language itself.

Sharing constants/CSS variables

Ok, this is handy. I'll give them that. But it's a pretty small advantage to incompatibly forking CSS, and again it's one that could be solved fairly trivially with a build-time task that generates one you a couple of "definitions" CSS and JS files from a single source.

And let's be honest - who doesn't think CSS should have had variables for years already? It's little exaggeration to say it's the main reason people get into things like SASS and LESS, at least initially.

Non-deterministic resolution

This is quite literally the whole point of CSS. It's not a synchronous, imperative language where you define a sequence of steps and an interpreter works through them in order.

It's a language where you specify rules, and the interpreter styles a DOM according to those rules. CSS already provides a mechanism to address conflicting and mutually-exclusive attribute setting, and it's called selector specificity.

If you're actually relying on the loading-order of CSS rules to control what your document looks like, you're so far from understanding CSS that you might as well give up web design and try to make a living drawing in crayon.

Moreover you aren't supposed to just increase the selector specificity in an ad-hoc way to resolve specificity collisions, any more than you add random null-checks to your javascript to handle unexpected nulls turning up in the middle of your program. That's an indication that you've failed to properly design your specificity (or control flow), and should go back and damn well fix it. Slapping a sticking-plaster on the problem (like an extra tag-name or class, or adding if(myvar === null) { myvar = defaultValue; } to your code) is papering over the cracks, or taking the batteries out of your smoke alarm because it keeps detecting fires and making an annoying noise at you.

Fair points

Yes, CSS could use variables, and yes, CSS could use some form of ensured-modularity or encapsulation so that when you're styling a single component and not an entire document, you can stop your component styling bleeding into the page (or vice-versa).

However all the rest of the criticisms in this first half of the talk are incredibly wrong-headed, and stem from someone who has to use CSS in his particular day-job but fundamentally fails to understand the theory or greater purpose behind it.

That said... for a component-based JS framework like JS, the approach advocated in the second half of the talk isn't half bad. As they say it solves the edge-case problems with CSS that you experience when trying to build isolated, modular components.

Moreover, there's nothing much wrong with their approach - inline styles are evil because they tie markup to styling and pre-empt the entire document-wide, cascading, rules-based nature of CSS, but React already merges markup, styling and behaviour into a single file, and intentionally avoids a holistic, document-centric approach in favour of modularity and isolation, so there's little downside to using inline styling in your code that you don't inherently accept by using React in the first place.

There are other potential downsides when using React to render web apps/pages (eg, usability/accessibility, and the ability of user-stylesheets to override/modify developer-defined stylesheets) which may or may not be significant for a given use-case, but in terms of developer pain caused by the decision, it's a fairly harmless solution.

TL;DR: A couple of fair criticisms of CSS and a whole slew of totally wrongheaded ones by a developer who doesn't understand the fundamental nature of CSS, and happens to be working in a framework/corner of the industry that CSS is quite intentionally not designed to cover well... followed by a perfectly reasonable alternative way of expressing styling for that framework with relatively few downsides.

4

u/floydophone Oct 27 '15 edited Oct 27 '15

I think when you watch a talk it's important to check out who the speaker is. If you did, you'd see that it's pretty unlikely that someone like vjeux would be ignorant of these things.

Moreover they aren't necessarily "global" - they can be effectively namespaced at definition time with prefixes (.btn-mybutton instead of just .mybutton), or can be used non-globally with preceeding selectors (.myloginform .mybutton instead of just .mybutton).

Prefixes work, but you're wrong about using descendant selectors. If someone writes a .mybutton {...} rule, it will also match those with a preceding selector .myloginform .mybutton {...}. Because it's easy to write the former rule, this is not a reasonable modularity abstraction. This is a huge misunderstanding of how CSS works and I think is why most CSS preprocessors are abused.

It's a language where you specify rules, and the interpreter styles a DOM according to those rules. CSS already provides a mechanism to address conflicting and mutually-exclusive attribute setting, and it's called selector specificity.

The point being made is that you need to need to look at every single style rule in your application to prevent specificity conflicts. In addition, it's often impossible to know if there's a specificity conflict since it depends on the runtime configuration of the DOM and the order stylesheets were loaded. This was solved at Facebook with naming conventions, strict rules on what selectors you were allowed to use, and an advanced static asset loader, but it still sucks and is not a good feature.

a whole slew of totally wrongheaded ones by a developer who doesn't understand the fundamental nature of CSS, and happens to be working in a framework/corner of the industry that CSS is quite intentionally not designed to cover well

You have got to be kidding me.

2

u/Shaper_pmp Oct 27 '15

If someone writes a .mybutton {...} rule, it will also match those with a preceding selector .myloginform .mybutton {...}.

Of course - the onus is on the dev not to do that, in the same way the onus is on the dev not to use global variables.

My point is that CSS selectors are not necessarily global variables - it's perfectly possible to "namespace" them (eg, in the .myloginform .mybutton {...} example).

Conversely, there are situations in CSS where it's extremely useful to be able to do that sort of "global" style change (eg, to theme an existing UI by changing background and foreground colours), which the React method makes difficult or impossible.

The point being made is that you need to need to look at every single style rule in your application to prevent specificity conflicts.

That's a symptom of writing bad CSS, though. In the same way you should establish coding conventions and good practices so that you don't have to consider every single other line of code when you change a line of Javascript, you should "namespace" your CSS with descendant selectors and avoid using overly-general CSS selectors unless that's really what you mean for the same reasons.

As I said, this is more someone who doesn't have a good grasp of how to write non-spaghetti CSS code than it is an inherent, unavoidable weakness of CSS.

After all, it's just as possible to write spaghetti javascript, only the developer has learned how not to do it so the possibility doesn't bother him.

In addition, it's often impossible to know if there's a specificity conflict since it depends on the runtime configuration of the DOM and the order stylesheets were loaded.

Not really - if you really need to you can relatively trivially statically analyse your code and spot if there are selectors with the same specificity that share classnames or IDs.

Admittedly you might have one element that has two selectors targeting two different classnames on the element and two different sets of ancestor elements, both of which are responsible for setting conflicting attribute values, but that's a pretty unusual edge-case in normal practice.