Hacker News new | past | comments | ask | show | jobs | submit login
Styling with Classy CSS (2006) (thedailywtf.com)
123 points by jacobr 6 months ago | hide | past | favorite | 67 comments



I feel like utility classes had their moment and we can now start to pull back towards semantic CSS with the help of new features like CSS custom properties.

Instead of .f-green in your HTML you can do --f-green in your CSS.

<header class="f-green"></header>

would become

header { color: var(--f-green); }

or if you really hate CSS and must stay in HTML

<header style="var(--f-green)"></header>

Though the literal naming is a touch too specific anyway. Something like this is wonderful:

--f1-color: green;

header { color: var(--f1-color); }

then you don't have to do confusing things like

header .f-green { color: red; }

because you can do

header { --f1-color: red; }

So we can be less specific AND more modular... because you can have that f1 (font1) color be red in your header, and still do:

footer { --f1-color: green; }

We can make really flexible and extensible systems with modern vanilla CSS. No frameworks or preprocessors needed.


It's extremely important to create classes like `.f-green` in case the definition of green ever changes. That's what we call forward portability.

Also, if your company rebrands from green to red you can just `.f-green {color:#f00;}` - it's so efficient!


This was the only bit in tailwind we modified a lot in our Config. You really need to remove the default colors and define them as [Primary, Secondary, Neutral, Warning, Error, Success] and then add variants of each. Then it really works. I honestly think this should be a default config change/setup option in TW. Nobody with a Design System/Brand guidelines should be including the default colors in their app.


I agree that you don't need the default colours, and in fairness this is one of the things that Tailwind fairly explicitly encourages. That said, I also used to use "primary"/"secondary"/etc names for the colours, but since using Tailwind, I've been using colour names directly (e.g. "blue" or for fancier design systems "mirage-blue" or whatever their name for their specific custom blue is).

I find it's helped for a few reasons, but the big one is just that it's easier to keep the colours in my head - I'm not thinking in terms of "tertiary-alt-3" or something, I'm looking at a design and going "that's green, which green? This green". I have more discussions talking about colours in terms of the standard English colour names than I do in terms of those colours' purposes in the design system, so the colour names seem more practical.

That said, I agree that spending some time switching the colours to whatever design system you're using us very useful. Another trick I've found is starting off a project just using raw CSS values (the `p-[8px]` syntax), and then when the basic designs are done based on whatever the designer has sent, getting a list of all the custom classes you've got and using this to define what the standard units are. This is helpful when the design guide isn't specific on these details, and the designer is being more freeform.


The biggest thing I've learned in making Tamagui is that the ideal setup is not to really have specific colors at all (unless you really really are just doing a one-off single color thing), but instead to let themes handle this (essentially a classname that changes out a set of CSS variables).

Then you can do things like `color1` (or `primary1` or `secondary2`) etc, keeping them generic. With this setup you can then re-theme any area instantly, no dark-x or light-x, no green-x. You can inverse an area to be light on dark, you can change the color out if need be.

We even go one step further (as an optional feature) where you can avoid the `color1` for many cases and instead use `color`, `colorHover` etc, which allows for having themes that change contrast or the strength of their various alternate states, but that's another story.

The site itself shows off some of this, but it's really quite nice. Now your "Notice" box can be alert style, or success style, with just a single `<Theme name="alert">`.


This is part of why we started down this path. We have a self-white-labeling product based on a JSON file loaded at runtime. Having this sort of theming is kinda a pre-req. but we are totally not blind to the ways we can play with it.


I would argue that all of what you just said is your designer failing you. For us, we defined the base sizing and colors beforehand and the designer works from there. We also use named color variables and themes in Figma such that an element with a background color shows the named color so I can just type in the same name in TW. Putting design and development at the same table on day one and getting both sides to speak the same language definitely speeds development and I really do think your life would be better for it. While your designer has you stuck picking 8px, 10px or 12 px, my source mocks are just .5rem or 1 rem and I can look at a design at this point and add the right value without even checking. You deserve better from your designer; them being 'freeform' is just them doing whatever feels cool this week and a whole lot of inconsistent values.


This is something Bootstrap does right, and has kept us away from Tailwind so far.


Or just use var(), which of course didn't exist when the article was written.

That way you can define your company's --brand-colour at the top of the file.


I used to think this way, but 1) it’s easy to do a find replace of f-green and 2) turns out no one we work with changes websites this way. The closest I’ve seen is changing a font site wide with some size etc adjustments


To be clear I still use semantic css and don’t use tailwind, but while aiming for pragmatism.


Nope. Green should give you green.


Or, like, off-green. And after midnight, green with all the blue taken out.


Yes of course. But not red.


It should be neither green nor red, but should describe the function. But Tailwind, that industrial CSS framework, has anyway moved far away from that.


I agree with the abstraction point. But if your tag says “green”, it should deliver green not a different color.


Except if you live in one of the many cultures that don't have separate words for blue or green. In which case all your greens should definitely be blue.


Yep, Tailwind didn't invent style tokens or composable classes! After learning Foundation, Tachyons, Material UI, Chakra...I was happy to see we finally settled on Bootstrap.

Oh, we didn't? Well, time to learn a new syntax. (Was it `dark:md:hover:text-slate-400` or `hover:md:dark:text-slate-400` again?) At least Tailwind arguably has more benefits than its predecessors.


What was the first "official" atomic css framework? I believe it was atomic.css[0]? In this style of css, tailwind is very much a latecomer.

[0]https://acss.io/


I think Tachyons struck the balance to be honest. Tailwind's "functions" and combinations seem to allow a higher level of complexity where it becomes difficult to quickly inspect a class block after some time has passed.


I will always argue against this. Keep your layout in one file and your styling in another. I've done more CSS than most in heavy web production and I never once had a reason to think something like this would be faster or more efficient.


CSS Utility classes are "faster" and that is the draw, but once they have been overused and abused, then you are either stuck with them, or you spend a lot of time cleaning the tech debt and rewriting the css properly.

At my current job, I work on a legacy application which is still actively developed and released. I spend a lot of my time cleaning up inline styles, styles that are applied via javascript calls, and style blocks on individual pages. I wish the inline styles would have been utility classes, because at least then they would be easy to find and replace, instead, there are "margin-top: 3px" and "margin: 4px 0 0" and "padding-top: 2px" and dozens of variations on that that had they just done something like ".mt-small { margin-top: 3px }" there wouldn't be so many variations and inconsistent looking pages. This company would have benefited greatly from Bootstrap or Tailwinds. I hate both of those, but there is no denying how easy they are to use and abuse.


Say more. What's the distinction between layout and style?


I've been a web developer for about 15 years now and I absolutely love Tailwind. I find it so much faster and efficient that it is really aptly named.


So visionary to be considered a wtf. Thanks for the submission, made my day !


Me too. This is really quite amazing in a small way. It really made me laugh.


This is what I did before stumbling on BEM - https://en.bem.info/methodology/css/


Now that you're familiar with BEM you can use the perfect css approach `.page__inner__title-f-green {color:#0f0;}` imagine the portability!


Or you can call the login box “.login” and style it.


Or you can have fun


Only when you don't live in SV. There you can't have the concept of fun.


Back in the day we made fun of this nonsense, now we freakin glorify it with libraries like Tailwind & friends...


CSS is one of the places in web dev that never really reached consensus, even today. We might get WASM as the app platform of the web before this even happens.


WASM is more of the same exact issue... web devs inventing fragmentation and trying to make things low level again even though they have such a great platform that's already batteries included...


Yeah. It's essentially a less verbose form of per-element style="..." attributes. It's weird to me that this is considered the state of the art today.


While I don't really like it myself, Tailwind is a good CSS framework for the age of component-based application design, where your JS / CSS / HTML lives in a single file, and your application-design won't change that heavily.

But when you want to redesign a whole site after the fact, or if you want to keep your component library logic & templates, and port it to a new system, Tailwind might be more trouble than it's worth.

It's just that... Atomic CSS has its benefits, BEM has its benefits, etc etc etc.


Why do you feel it's nonsense? I'm genuinely curios.

Personally I'm using Tailwind for 90% of the styling. If I keep repeating a certain combination of classes often, I'll group it with a custom class. (Edit: See colejohnson66's comment for an example)

Two advantages of tailwind that I didn't see before I started using it:

- It's often easier to find what I want in the tailwind documentation, and it comes with nice examples. MDN is great, but with Tailwind I get reasonable presets.

- TailwindUI: Saves me a lot of time and looks good without feeling as generic as bootstrap.


Perhaps I'm just old-fashioned but I prefer semantic classes.

I completely rewrote the CSS for my website and I did not need to touch the templates. An .error is an error and a . collapsible is a collapsible. Their exact style is not dictated by the markup.

I also like that it keeps the markup small and easy to read, because it's not peppered with CSS.

It also avoids situations where two widgets look different because I forgot to copy one class over. A .collapsible is a collapsible.


Semantic classes make sense for small and brochure-style websites. For any moderately complex website or web application, your class semantics quickly become a challenge. Naming things is exceptionally hard, especially when each "component" can have multiple variants each with their own modifier classes e.g. `alert alert-danger alert-with-icon alert-collapsible alert-expandable alert-hidable`. Multiply this by hundreds of components and you find yourself in class soup that's almost indistinguishable from Bootstrap and Tailwind. So I've given up on semantic naming because it's futile for ambitious projects.

Restyling a website without changing any of the markup is a pipe dream from the CSS Zen Garden days when websites were much simpler and more static. Apart from small/personal/static websites, it just never happens in practice today.


If there were more opinionated frameworks actually meant for that kind of restyling, I don't see why it wouldn't work, at least some of the time.

Why do we need all these different classes? One CSS class can handle the presence or absence of a hide button just fine, and lots of frameworks just have .danger set variables or override colors, staying pretty much universal.


As someone who has consulted on more enterprise level websites than I can count, this has not been my experience at all.


Can you point me to an enterprise level website that uses semantic classes?


I cannot, for professional reasons, point you to any that I have personally worked on. However, Smashing Magazine (https://www.smashingmagazine.com) comes to mind as one of the early adopters of both highly semantic BEM and an SSG methodology.


Tailwind is one of those polarizing topics where people either love it or hate it. I've used it at a few companies and I didn't care much for it, but I had coworkers who swore by it.


We've been using it for a little over a year. So far my biggest finding is that Tailwind works best when you have a UX team that is forced to play by the same rules. In that context, with a heavily chopped down tailwind.config, it comes alive as a utility. It can even act to proof mistakes in the UX work. A div with a 1rem padding, with a BG of neutral lightest and a text color of "primary" is a spec defined by class names and a mock. I honestly think that in uncontrolled environments without a singular design system and without configuration, tailwind can become a mess. I really do not care for the out of the OOB config, it is way too free on color schemes. You need a few people to play the rulemakers and constraint for it to be helpful.


> Tailwind works best when you have a UX team that is forced to play by the same rules

I agree but found that Bootstrap (>v4) to be better at this. Instead of every possible color and tweakie, Bootstrap has pretty decent utility classes that are semantic, and in addition to all the basic components like button, etc:

https://getbootstrap.com/docs/5.3/utilities/background/


My gripe with Tailwind is the redundancy of class definitions across elements that clearly would benefit from "normal" CSS. If I have a <table> with a whole host of <td> elements, those repeated class definitions become quite tedious.


Use PostCSS:

    .myFancyTable td {
        @apply p-4;
    }
The advantage of Tailwind, IMO, is that styles for one-off components (like a breadcrumb bar) can just be written inline instead of in a separate file. But reused components like table cells should be using CSS selectors.


Congratulations, you have reinvented the purpose of CSS classes. This is why I don't use Tailwind, at a big enough scale, it becomes lots of duplication, and if you use @apply, it's just...CSS classes as originally designed.


Part of the problem with the tailwind debate is that the appeal of tailwind is not just having your styles in your html, it's also having predefined style units, e.g. size intervals for things like margins.

CSS variable libraries like open-props also do this, only without the controversial use of utility classes. Add editor snippets to that and you have nearly the same ease of use as tailwind.


I still think it would be nice if CSS natively allowed you to combine classes the way these @extend and @apply operators do


In practice, I never have found much benefit to that. If I need a base class, I will create a base class. .validation-message for instance, then if the validation is a success/error/warning/info, I will write those classes, then my validation message element will have 2 classes on it "validation-message warning"

That way there is no repeated rules like in the final compiled @extend/@apply operations.


You can't reinvent something that was never invented to begin with. "CSS classes"? ("as originally designed"?)

Class definitions are not CSS. They're markup. The CSS selector language does let you target them (with a leading dot, as in .foo)—just like CSS lets you target other things defined in markup with special syntax: element IDs (#bar), attributes ([foo=bar]), etc. It's not as if HTML existed without classes and without CSS, and then CSS was invented and with it came classes, too.

(This isn't to say that you're alone. A frighteningly high number of people reveal through their choice of language an apparent belief that `class` was invented by the CSS working group (or something). That when you're writing HTML, evidently 95% of it is HTML proper, but then when you get to the part where you type out 'c', 'l', 'a', 's', 's', that you're shifting into CSS and it's like, "This last piece with these "classes" was contributed by the CSS folks, and so that's why/how CSS leaked in," without ever seeming to realize that... they're not actually writing CSS. It's still just markup—using the ordinary syntax for specifying attributes and their values. The CSS only happens when you, uh, start writing CSS...)


And then you are just writing css with a more obtuse syntax.


Cool. So @apply is basically a way to compose classes from other classes?


This was already an option with Sass's @extend (later ported to a PostCSS plugin)


Isnt this only a problem when the table contents are hardcoded ?


It was just an example, but it's more broadly the redundancy of a list of repeated classes applied to elements that are identical or mostly identical.

These are things that CSS literally solved with the web2.0/semantic-web movement 20 years ago. I get the convenience of Tailwind but a lot of it feels like a massive step backwards.


The big thing about tailwind in the context of JS rendering is that this ends up being a code smell. If you find yourself repeating a set of classes...you probably should componentize that and DRY.


It's funny how the solution (use CSS as it was intended) is now being transformed into JS-powered component solutions.

But yeah take say a dashboard layout with a lot of cards of different sizes. They're going to have the same underlying design, padding, rounded edges, background colors, etc -- and usually only vary on maybe size and breakpoints.

This is all very well solved in semantic web, but it feels to me like the JS + Tailwind apporach is creating new problems and thus new solutions to accompany.


I think the detail is that this JS answer is really only for people working at a seriously large scale. At that size, there is absolutely zero room for non-componentized logic as cross-managing a billion pages with duplicate HTML elements is pretty unacceptable. That said, Tailwind also allows you to define your own classes that apply multiple TW classes.


> This is all very well solved in semantic web

If it was solved with "semantic web" (whatever that means), we wouldn't have people attempting to solve this again, and again, and again.


> If it was solved, people wouldn't try to solve it again.

Remember when serverless got invented even though CGI already existed?


I'd say it was rebranded :)


That's patently false. The webdev community does nothing but reinvent/rediscover the wheel e.g. SSR.


What does SSR have to do with semantic web?

All "semantic web" can provide is a flat CSS namespace and a bunch of nested divs.

Even if you do everything right there's nothing semantic about it: https://inclusive-components.design/cards/


At a certain scale, Tailwind becomes a write-only DSL. It's almost inscrutable if you want to change something on some heavily classed HTML tag.




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

Search: