Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The problem is that I’m not convinced that “good CSS” even exists. Even the very idea of separating content and style seems problematic to me, and in my experience it simply doesn’t works for anything more complex than a markdown converted to html.

Add to it that for some weird reason web’s style includes layouting, which imo should be a separate thing entirely, and this is the primary reason why any given CSS has to be specifically created for a given HTML template, and why seemingly benign CSS modifications can move that 3rd step of the checkout page, rendering it completely broken.

Restricting CSS to a subset of only cascading some very basic properties (fonts, colors, default font-size), and letting everything else be managed on a per component basis (where close coupling of style and template absolutely makes sense) and simply layouting those components to form the given design makes much more sense to me (and frankly, it was sort of figured out a few decades ago by several desktop GUI framework..). And while you can write vanilla CSS this way, tailwind just restricts you to this subset — the same way there sure exists some safe subset of C, but you need something like Rust to restrict you to that [1]

[1] I know, this is not really how it works, it’s only for the analogy’s sake



> Even the very idea of separating content and style seems problematic to me

When I try to "separate" CSS, I always end up creating utility classes (so kind of like Tailwind).

Currently, I like to use a combination of utility classes (e.g. class="text-bold") and high-level class modifiers (like a ".pricing" wrapper, and then I can modify everything inside the pricing section like spacing, font sizes, colors).

    .pricing h2 { color: var(--color-tertiary); }
I think this makes more sense than adding "color-tertiary" class to each h2, because if I want to change the color, I would have to modify it in all the h2 tags.

I would use "text-bold" if there is a one-time instance where I want the text to be emphasized. If there can be a rule extracted (e.g. make every first word bold), I would use CSS selectors/classes to modify all those instances.


Why is the component-based approach to CSS not working here? Am I missing something?


I'm far from being even "above average" at CSS, but this approach (as a long time developer, mostly in OO) has made the most sense to me. Little bundles of things in their own contexts that apply to a limited area. I can re-use names as they are appropriate for their contexts and not worry about cross contamination.

But, other people do things differently so maybe it's not the best approach for them; but for my limited needs and experience, it's been fine, if not great.


How would you maintain a reasonable "component-based" approach without something like scss? I'm legitimately curious.

Otherwise, you have to take great pains to ensure styles don't conflict or accidentally apply to things they're not intended for. Or you have to use some other framework/tooling to convert your css selectors and markup so that scoping is enforced


Shadow DOM works well for this if you need true encapsulation.

A blend of shadow and light DOM in web components solves most of the issues I've run into over the years.

It's also easy to scope styles to a custom component in the light dom with:

    my-component .header {...}
I do this a lot in light DOM web components and render the styles with lit-html as part of a template.


There is also the ::part() selector now which is quite useful for selecting things within a shadow. https://shoelace.style/ uses parts for styling individual parts within custom elements.


In practice, I've found that to be pretty unwieldy and difficult to use.

My general approach is to keep most application level components in the light dom for styling, and only use shadow dom for library-like components, mostly layouts for slotting light dom stuff.


Web Components use of the shadow DOM is designed for this very use case.

I never have to worry about clashes or getting too cute with my naming conventions. You can just use a h1 selector and not think about it.


Very interested in learning more about this. Do you know if there are any open source projects I can take a look at?


This is in some places a little bit specific to Lit but mostly not and walks you through that shift in mental models from start to finish that tends to trip people up a lot coming to Web Components https://youtu.be/Xt7blcyuw5s

FWIW if you are interested in Web Components I would say Lit is hands down the best entry point I’ve come across. Strong recommendation and nullifies most of the common complaints you tend to hear associated with them.


https://shoelace.style/

And here's an experiment I'm working on, where all styles are scoped to components because all static DOM trees become custom elements with their own shadow root: https://github.com/aalin/rdom


Great question.

Simple linting rules can get you lots of mileage here. First and foremost, you ensure that in any component CSS file, ALL selectors begin with a class that mirrors the filename.

It seems to me that this can prevent the vast majority of conflit or spillover occurences. Don't you think?

Legitimately curious here as well!


> First and foremost, you ensure that in any component CSS file, ALL selectors begin with a class that mirrors the filename.

But then you're adding a convention that isn't as easy to follow. Maybe you follow it, but what about new people. What about people who make a typo? Are you going to make a VS code plugin that points out if someone mistypes the file-based class in the CSS file?

What if the file is renamed, or moved? Do you then have to go update every selector in the CSS file?

This all seems so much more brittle to me than just using tailwind, and the VS code plugin show you the possible class names you can select from when you start to type something, as well as rules for each of those class names. It also catches (and highlights) contradictory rules, when applied to the same element. You can't do that from the CSS (there's no telling what the declaration will be used for, from the css in isolation), and unless you make your own editor integration, this won't happen when editing markup either.


What is the convention? Beginning selectors in a file by the filename only? If I understand correctly, then I'd fallback on the linting.

If the file is renamed, then yes, you change the selectors. That's a simple operation. But I think the same goes for any JS framework where you'd create components. If you change "button" for "secondary-button" you'd have to change it in at least a couple of places I guess? Either way, you should limit these kind of operations to a minimum.

And what if I don't want to use VSCode? Maybe there are Tailwind plugins for every text editor...

But more importantly, that's quite easy to include your CSS files in the autocompletion of, for example, Sublime Text. I'd guess it's the same in VSCode. And again, simple linting should prevent much of these problems I think. You can easily lint contradictory rules in a ruleset. Stylelint would be perfect for that.

And if by mistake you have contradicting rules across rulesets, then a quick look at the devtools will tell you where the problem comes from. On a sidenote, the devtools become real difficult to use in a Tailwind-like paradigm.


> If you change "button" for "secondary-button" you'd have to change it in at least a couple of places I guess?

I'm not sure I understand this argument. If I rename a component and the file it's in, I get automatic import renames across the codebase without having to do anything myself. And if I didn't, I'd get errors trying to run the code (I'm not sure how you'd configure CSS to do the same thing with unmatched selectors, though I guess you probably could remove them from the output at least with postcss)

> And what if I don't want to use VSCode? Maybe there are Tailwind plugins for every text editor...

You do you, but according to the 2020 state of JS, 86% of JS devs were using VS Code, and 20% vim (which also has tailwind support): https://2020.stateofjs.com/en-US/other-tools/#text_editors

They removed the question so I don't know what current trends are, but Tailwind is at least supporting 90% of possible users with just those 2 (and I haven't looked into support for other IDEs)

> On a sidenote, the devtools become real difficult to use in a Tailwind-like paradigm.

I haven't found this to be the case at all, I'm not sure why Tailwind would make the devtools more difficult. If anything, it makes it easier since I typically only have to look at the CSS section for elements which have inherited styles


A simple find and replace would do the same then for a CSS change. Again, that's not something that should happen often.

As for support in text editors, you can still autocomplete any class you have in your CSS. And the CSS linting will give errors too if you have problems. And there are CLI programs for discovering unmatched CSS, which works pretty well in my experience.

And the devtools suffer from all the added classes. It can slow down to a crawl depending on your machine. And you can't play as easily with the styles... If I disable a property in the cascade, all other items with this property will lose it. I would say it goes against the devtools grain. But I guess it depends on your usage.


Separation content and style works perfectly well. Just people never bother to learn neither HTML nor CSS and rely on some generated monstrosity, be it generated by WP or React.


It works for me mostly only theoretically. When I have to apply it at scale I run into the practical problems that people mention here; 1 big namespace, mostly.


Do you mean conflicts or spillovers?

Because, as I said elsewhere in the thread, I think (maybe wrongly) that simple linting could rid you of the vast majority of these problems.

But, please, if you mean something else, do comment! I very much like this discussion.


For me I meant coming up with a name that semantically describes this area of the HTML, that I haven't already used.


Well, don't you already name component file after it? Maybe I still misunderstand...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: