Hacker News new | ask | show | jobs
by vpfaulkner 1842 days ago
My gripes with traditional CSS styling are:

- Styles are global

- Styles are targeted via brittle, untyped, and opaque "magic strings” basically. This means mistakes are more likely to be caught at run time than compile time. Eg, I wouldn't get a compile time error if I did `position: oops` or `class="oops"`.

- Styles are often "far away" from their target which makes mistakes more likely; ie this deeply nested HTML element in one file is coupled to a deeply nested style sheet in another file

- It is easier to perform complex manipulation of styling if it is made up of JS objects. Eg, if I wanted to do math or I wanted one style to be a function of another (eg `marginLeft: PAGE_MARGIN`)

That being said, I’m sure there are some better ways of doing traditional CSS since I last tried it that I’m unaware of...

As far as the performance trade off, I'd love it with styled components did not come with this but, at least for my use case, it is usually worth it

7 comments

"Styles are global" is changing :)

https://youtu.be/jUQ2-C5ZNRc?t=683 Looks like the spec is at https://drafts.csswg.org/css-scoping-1/ with examples like https://drafts.csswg.org/css-scoping-1/#example-f1503361 and more details at https://css.oddbird.net/scope/

Still experimental of course, but could be very useful if implemented alongside Shadow DOM. Note this isn't 2012's scoped CSS: https://caniuse.com/style-scoped

If we get this the only thing I'll continue to dislike about Web Components would be the global namespace of web components and that Web components HTML attributes can't be rich objects or arrays natively. (I'd love it if web browsers simply implemented JSX, for example, or a syntax that looks like DOM but is actually a function call that can produce DOM. Bonus points if they also implement Markdown or MDX as an HTML element of some kind.)

CSS scoping without a hacky third party framework is long overdue.

Web components largely failed at this point though, the spec needs to be rewritten from scratch to be more pragmatic. People have been using React and Co for more than a decade now, spec writers certainly have enough hindsight as to how people practically program front-end applications.

People have been using XBL in Mozilla before all the web components work started, so… I wouldn't hold my breath.

Looking it up, archive.org says it's been over 20 years… https://web.archive.org/web/20001218094100/https://www.mozil...

Please give me web-components without Javascript and I'll start using them heavily.
well, it was kind of the whole point of XHTML2 spec. The Web component spec is just an inferior version of it, that's why it failed.
Web components are a great brand for a collection of mostly awful APIs. Shadow DOM in particular should have just been a CSS property from the start. Glad to see someone starting to recognize this.
Never-mind, read the link. It's just shoveling more crap on top of the existing shadow DOM instead of finally just cutting bait and making a CSS property called `inherit: reset;` like they should have done to begin with.
CSS modules with TypeScript solves the first three items pretty neatly. You write CSS that lives alongside tour component, then import the file into your component and apply the classname to your elements. It compiles to unique classnames that cannot conflict with any others. And with TS, you’ll get a compile error if you use a class that doesn’t exist. The last point is possible either with CSS vars or Sass vars. calc() can handle some pretty complicated math. You can also do plenty of math in Sass.
Are there any good examples or tutorials for using CSS modules and TypeScript as you described?
I don't know of any full tutorials that cover both, but this is an ok rundown on how to use them in JS: https://css-tricks.com/css-modules-part-1-need/

This is the webpack loader that generates type def files: https://github.com/seek-oss/css-modules-typescript-loader

I've really enjoyed tailwind after using styled for a while.

At least for my applications, the computers my users run on can't handle the performance implications of styled.

But beyond the performance, I legitimately build faster using tailwind. I also find it easier to understand the components others build as well.

We’re making the switch at the moment and, after a bit of a learning bump, everyone is flying along with it now. It’s basically inline-styles++ with having all the context right there but not having the edge cases that require breaking out into classes to use media queries etc.

It was a little struggle at first with our previous setup, but I spent a week or so moving everything over to Vite with hot module replacement which has been life changing.

Completely agree.

This whole discussion feels silly after a day building things with Tailwind. The system, defaults, docs and tooling are excellent.

And dev speed is ludicrous.

Fully agree. It's usually the people that have never worked with it that share their opinion, always ending with "why do we need this"

Can encourage others to give it a try as well. Dev productivity through the roof indeed :)

Comparing Tailwind with Web Components might be a bit unfair. It is well known that Web Components have terrible dev ergonomics.

It would be more fair to compare with frameworks that work with scoped styles (such as Svelte or Vue’s single file components). Developing in these is also an excellent productivity boost.

Can anyone give some references on that Web Components have bad dev ergonomics? Is it just that Web Components don't allow passing of complex types so you have to stringify everything?
I see many people have problem with that in the comments here. However I don’t find that to be an issue. Passing properties (as opposed to attributes) allows complex types and many popular frameworks have a handy shorthand for it (e.g. in lit-html you write `<my-component .prop=${[1, 2, 3]}>`).

In my opinion the bad ergonomics is actually when authoring the components (not consuming it). Many of the faults have been excellently pointed out previously[1]. The most glaring the boilerplate you have to write if you want your attributes to reflect a property.

This has an easy fix though, which is that you simply don’t write your web components by hand. You either use a library (like lit-element[2]) or a compiler (like stencil[3]). I’m personally waiting for a less opinionated compiler with a smaller runtime then stencil (preferably no runtime; perhaps that is Svelte with a web component target, I haven’t tried it).

There is also a proposal for a declarative shadow DOM[4], which aims to tackle some of the bad dev experience we have with web components. However I’m personally a little skeptic that it is a good proposal, or that it will fix what most web component devs are concerned about.

1: https://dev.to/richharris/why-i-don-t-use-web-components-2ci...

2: https://github.com/lit/lit-element

3: https://stenciljs.com/

4: https://github.com/whatwg/dom/issues/831

It is not well known that web components have terrible dev ex, because it isn't true.
Trying to get my team to consider the switch from Bootstrap to Tailwind. All of this talk makes me jealous
Nothing beats a live demo.
Haven't heard of this until now. Looks like a cleaner version of Bootstrap?
It's kind of like bootstrap except it's more focused on the developer building styles instead of having a number of prebuilt styles.

It also is more based on what css can do instead of having it's own abstraction. Most of the class names in Tailwind are very close to their css key+value equivalents. For example if you wanted to write `float: right` in css you'd use the Tailwind class `float-right`.

>"- Styles are global

- Styles are targeted via brittle, untyped, and opaque 'magic strings' basically.

- Styles are often 'far away' from their target which makes mistakes more likely; ie this deeply nested HTML element in one file is coupled to a deeply nested style sheet in another file"

You can get a long way to solving those three issues with good organization, but only if you control your whole project, stick to the plan, and don't have any libraries.

But over the course of a long lived project CSS is a real foot-gun that even well meaning developers will shoot themselves with. It's hard to unweave a tightly woven CSS nest, and once you introduce third party libraries and custom CSS things start to get wild. Who hasn't seen a "custom.css" overriding the "global.css" which was itself just a bandaid to fix an issue with some third party library.

I use a method I called "Contexts and Components". It starts with a reset. 98% of the CSS is inside the component files, and target component classes, eg <div class="product-card">. But of course things can change depending on what page they're on, and those are called contexts. Maybe a product card on the home-page has a border or whatever. That gives you a way to address client requests for things to differ but without making crazy complicated configurable components.

That way things are really shallow, only one level deep unless they are modified by a context, which makes it two levels deep. I find I need way less CSS, no crazy hard to reason about selectors, and it's all very easy to understand. Best of all, it's easy to remove stuff entirely, so you don't end up with overrides over overrides.

I keep going back and forth on this one. Right now I believe it's best to not fight against CSS and use it as it's meant to be used.

I try to focus on writing nice HTML often multiple relevant class names. Then later make things look the way I want in CSS.

I find it hard to think in CSS in translate that to HTML but a lot of developers I know tend to work that way.

Complex manipulation can easily be done with a preprocessor. You can work around the other issues you mention by just, well, learning css instead of fighting against it.
You can address points 1 and 3 via (s)css modules.

But point 2 and 4 stand.

You can also kind of address 4 by using `calc` and custom properties in CSS.

(eg: `margin-left: var(--page-margin);`)

We started using CSS in JS a few years ago because we couldn’t, and still are unable to use CSS variables (some of our customers still require IE11 support and we can’t drop it until 2022).

The main issue I still see with CSS variables is IDE support and static validation. With my CSS written in typescript I know that every variable I’ve imported works statically.

Point 2 is solved if you add TS to the css modules.