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

The ultimate anti-pattern of this philosophy is Tailwind.css (the newest, "coolest" css framework). Not trying to hate on it, but I find it ironic that the whole point of Tailwind is that you can basically style your entire website within the HTML, without needing to customize it with CSS.

For someone who learned CSS during the CSS Zen Garden era where we were told to only use the HTML document for structure and never style, it makes Tailwind cringe-worthy.

Yes, I know lots of people customize it and stuff, but the idea still stands that 95% of styles are done within the HTML document through tens of thousands of ultra-specific css classes which basically just tweak a single css property.



I also grew up in the CSS Zen Garden era, and I've become a big Tailwind proponent.

To me what is cringe-worthy is hanging on to ideas about what this medium is that just no longer apply. For better or worse, the web stack has been appropriated into an application framework. I am not making documents that have styles applied to them. It's just not a metaphor that works anymore.

The HTML, Javascript and CSS in a single-page application are not separable in any meaningful way. Maybe for some parts of your app, you can maintain this separation of you try, but it's not something that adds any value at all. Even if it could work, there would be absolutely no reason to try. The type of redesigns I do on this type of code affects HTML, Javascript and CSS equally, always.

Tailwind, to me, solves a bunch of very real ergonomic issues when working with large web applications, and results in far clearer code.


>The HTML, Javascript and CSS in a single-page application are not separable in any meaningful way

This is orthogonal to the issue. It's still possible to separate the functional layers of a website or application, even if the entire stack is JS or whatever.

I don't see how single page apps invalidate the base concept of separating data, structure, and styling into separate layers, regardless of the format or code language of those layers.


SPAs don't invalidate the concept of separating structure and styling, but as with all technical architecture decisions there are tradeoffs. Whenever you add another layer you are paying some base overhead cost with the goal that each individual layer ends up simpler. Whether or not this is a net win depends largely on the interface between the layers (see also: microservice trainwrecks). Content and style is tightly coupled and application-dependent, so abstract principles that sound good may make zero sense in a particular use case depending on a whole slew of technical and operational concerns about how the markup and CSS are generated and served.

In the old days, website were primarily documents, and as browser formatting grew more sophisticated the ratio of content to styling markup grew lower and lower, and when you're formatting simple documents the amount of redundant styling is very very high. Because HTML was designed with a small number of elements that provide pretty good coverage over basic documents, and because most documents were created by hand, the original CSS design and philosophy behind CSS Zen Garden was an absolute slam dunk for content creators of the era. The assumption is a small amount of CSS covers styling for a huge library of markup documents, minimizing overall code size.

As web apps evolved to be more dynamic, first with bits of AJAX and then graduating into full SPA with more and more functionality ported to client-side APIs, we found the semantics of HTML which were tied to more universal concepts of written documents (heading, paragraph, list, quote, etc) did not cover the semantic needs of describing UI widgets. At this point CSS is still useful but the optimal structure is not as obvious. Essentially there are two extreme approaches: 1) create very specific markup for each UI element, which optimizes markup size and clarity, but leads to a huge amount of duplication of CSS; or 2) create UI-oriented classes that are then tacked onto a dense tree of nested divs, which optimizes CSS size and clarity, but leads to markup bloat and "class-itis".

This fundamental problem was attacked from many different angles, lots of code generation, web components, OOCSS, BEM, Sass, etc. I consider Nicole Sullivan's work in this area to be seminal, leading to the optimal approaches large web products use at scale, and directly informing the design of React and modern SPA approaches. The reason Webpack processes markup, css and javascript all together is because things are so tightly coupled in practice, that you need tooling to optimize overall code structure and legibility. Purist approaches don't work very well for large projects because HTML & CSS were not designed to build GUIs.


>Essentially there are two extreme approaches: 1) create very specific markup for each UI element, which optimizes markup size and clarity, but leads to a huge amount of duplication of CSS; or 2) create UI-oriented classes that are then tacked onto a dense tree of nested divs, which optimizes CSS size and clarity, but leads to markup bloat and "class-itis".

Really, only two approaches are viable? There's no middle ground here? What would be the point of highlighting the extremes?

It's as if the entire tech industry has lost the ability to tell a designer to sit down and come up with a basic typography set and color palette even. Obviously you can't just create the entire style sheet set in one pass, but can't there be an iterative approach rather than throwing the entire thing out and building giant systems just to let picky designers pointlessly tweak small pieces of the application, in isolation?

What does a complex, "dynamic" widget have to do with not using standardized typography and colors in your application? Once you start there, can't you just evolve the styles to meet product needs? It just seems to me that 99% of the time, the point where it's decided that this whole thing should be thrown out, is almost always the point where someone wants to put "built a component system" on their resume...

Another grey area:

>create very specific markup for each UI element

vs.

>create UI-oriented classes

There's another middle ground here where you just have really big CSS selectors, and many things share styles, while still pointing to structure-oriented html classes. Can you achieve a middle ground better than individual styling, without resorting to UI-classes?


That's exactly my point, the two extreme approaches are on a continuum, and the interface between the two is very tightly coupled, leading to the optimal approach for a typical SPA being very different from the approach being touted in the Zen Garden era.


Can you give an example where CSS is duplicated?

div's should be avoided. Use semantic elements instead! If you absolutely need them you should consider making a custom element instead. (with it's own base CSS).


> I don't see how single page apps invalidate the base concept of separating data, structure, and styling into separate layers, regardless of the format or code language of those layers.

It does not. But using utility-first frameworks like Tailwind doesn't mean you're not separating things. It just means you're not separating things in CSS files. You have the Tailwind setup (which allows you to customize colours, spacings, etc.) and the functionality of whatever component framework you're using. The point is that in the context of SPAs, "styling" (visual presentation) is not limited to CSS.


This seems backwards. Desktop/GUI application developers have separate layout/theming engines and you don't see them asking for theming frameworks to be intertwined with components properties.


> The HTML, Javascript and CSS in a single-page application are not separable in any meaningful way. Maybe for some parts of your app, you can maintain this separation of you try, but it's not something that adds any value at all. Even if it could work, there would be absolutely no reason to try. The type of redesigns I do on this type of code affects HTML, Javascript and CSS equally, always.

I've heard different forms of this argument for decades in dozens of systems. Same old "why pay for abstraction" argument. I'm not going to answer. Either you figure out the answer or you don't.


I'm not saying you shouldn't make abstractions. I'm saying that Tailwind (in the context of a SPA framework) makes for better abstractions than traditional CSS.


> I am not making documents that have styles applied to them. It's just not a metaphor that works anymore.

And xml-based markup was just never a good format for that. The concept lives on in markdown, and in CMSs like WordPress, where an author creates content in a common format that is styled based on site- and page-specific rules

No one wants to write in html. If you’re working in html directly, it’s probably because you’re building something more complicated.

(If any of those assumptions are wrong, tell me! I’d love to hear a counterargument on why pure html is a great format for producing content!)


Maybe for 80% of people, it doesn't matter that your HTML isn't semantic, but for the 20% of other people who have need for accessibility features, that's basically the same size as the entire market of web browsers not named "Google Chrome".


You are conflating unrelated things.

Using a framework like tailwind does _not_ affect whether your actual HTML elements are semantic, which is what would affect accessibility.


That arbitrary separation never made sense, when HTML always harbored presentation information. From controlling the cascading of styles to spatial layout, your HTML and CSS are tied.

The separation of concern that actually makes sense, and on which we ended up, is structured data (JSON) piped into a presentation layer (SPA lib like React). That's what XML tried to do before it became gimped as HTML.


Not at least with HTML 4 and XHTML. HTML didn't harbour presentation information. It told the browser the structure of the document.

If you look at other document writing system such as LaTeX. You will see that there are Sections, SubSections etc.

The link to the CSS simply told the browser how these should be presented. LaTeX has something similar as you can create a document class and Word has different styles you can import.

Having a concept of a document structure with a set of styles attached which you can change easily is a good idea.

The HTML document should make sense without a style sheet and if you write/generate semantic markup it does work properly.


> Not at least with HTML 4 and XHTML. HTML didn't harbour presentation information. It told the browser the structure of the document.

I disagree. Unlike JSON which is truly presentation agnostic, the position of the HTML elements always did affect the layout and some designs were pretty much impossible to achieve without having to move HTML elements around. Despite the popular claim to the contrary, HTML was always part of the presentation layer.


> position of the HTML elements always did affect the layout and some designs were pretty much impossible to achieve without having to move HTML elements around

The results you see on CSS Zen Garden show that this is not true at all. It was hard, but not impossible then and nowadays grid layout and CSS3 fixed a lot of the issues.


> It was hard, but not impossible

Oh great let me get right on that. Wait, no, I have far more important things to do with my time.


Like leaving snarky comments on here?

Have you deliberately ignored the rest of the sentence? CSS3 and display grid solved a lot of the issues. It is supported by any modern browser.

Leveraging grid layout makes for a complete separation of concerns and still keep semantic markup without any hacks that only add to the amount of work. Take just a couple of hours of your very important time to learn it, and you might see the payoff.


To achieve that tho you need a ton of superfluous non-semantic html wrapping everything in triple so that you have the flexibility to do what you need.


Again, not true. Take a look at the HTML from the Zen Garden page and you will see it is very semantic.

Also, just anecdotal: I am working on a Vue.js component which I want people to customize the styling however they want. This is forcing me to drop the CSS part of the components. I am not adding any cruft HTML and yet I did manage to get a "basic" theme and a good chunk of the "materialize" look already. Two themes, two separate SASS projects. It can be done.


The main (only?) way html affects style is containment - the hierarchical nature of it and the ability for components to be "inside" other components. I feel like I already bump into this issue quite often with something as basic as whether an <input> should be inside the <label> or next to it. The only way, I believe, to resolve containment issues is with absolute positioning (right?). Given enough time and change requests, every element will eventually have to become absolutely positioned, which would become a mess - do you agree with this and how do you handle it?


I am not a frontend specialist, but "display:grid" solved a lot of these issues for me. You can define even template areas and make things responsive with align-self, justify-self and related directives.


At the time CSS wasn't as feature rich as it was today. The problem was a lot of the time the designs didn't respect the medium at all. There were even designs that were impossible. The technology was being pushed to do stuff it wasn't really supposed to do.

You are complaining about the wrong thing.

> Despite the popular claim to the contrary, HTML was always part of the presentation layer.

Not at all. It is document format. Designs that do not respect that doesn't change it's intrinsic nature.

This is like complaining that a shoe isn't a very good mallet.


Apart from the false dichotomy (the fact that HTML is a document format and that its structure plays an important role in browser layout are both true), I totally agree with you. HTML was indeed never meant for that but it was often sold as such by evangelists, hence the last remark (I wasn't complaining about HTML).


HTML didn't harbour presentation information.

That's not entirely true. Even ignoring the elements that were explicitly about formatting and have since been deprecated, the order and nesting of elements could have a profound effect.

For example, the entire model for how to do layout using CSS floats fundamentally depended on the order of elements in the source HTML document. It wasn't until much later that CSS finally added tools like flexbox and grid where you could explicitly reorder the content from multiple source elements in the rendered output using CSS alone.

Even today, certain effects such as column-based formatting for a table are much easier to specify in CSS if your HTML has additional elements such as <colgroup> included, yet there is little reason to include such elements in the markup except to support that kind of formatting.


What you are talking about is the still part of the document and the document structure. Generally where writing something you will have a beginning, a middle and and end of a document. You will have parts of a document that will have lists, tables etc. These are structural elements. You can look at the markup itself (if done semantically) and you will be able to ascertain its meaning.

Yes a table will need to have the correct elements in the right order. This isn’t presentational it is semantic.

HTML5 does this better than HTML 4 as it has more semantic elements as a response to the more complicated layouts of modern web pages.


Enjoyed reading your POV on this. Thanks for sharing.


Sure you could do everything on the HTML with Tailwind but they do recommend composing component classes for regularly used things. I’m not saying that solves all your concerns but it helps.

Abstracting out CSS into utility classes can make it much quicker to get a consistent looking site up while still giving you a little more control over the look and feel. Of course you can misuse this but I think people who don’t understand standard CSS make a much bigger mess of it than if they have something like Tailwind.


Problem with pure CSS is that when you work in teams very quickly you start getting a lot of redundancy. People reinvent already existing styles, copy/paste code all around with just minor differences, color/padding/margins inconsistencies are introduced, you get dead classes that no one dares to delete, etc. The solution is usually to have one person define all the core styles for all components, and then you mandate the rest of team to re-use them as much as possible - which basically boils down to the same thing these frameworks provide, just someone else did a lot of that initial work for you. And if you don't want to use all those utility classes directly in the html, you can use components and @apply to group them into more semantic classes. Still you get the benefits of having ready made utility styles, and also of using the system that a lot of people is familiar with and can quickly onboard the project.


Checkout Adams (tailwinds author) reasoning

https://adamwathan.me/css-utility-classes-and-separation-of-...


I’ve followed a similar path but since become a huge fan of Tailwind’s compositional style. It refactors style at the point of HTML generation, which in this component oriented era makes a ton of sense.

CSS was explicitly designed not to be Turing complete. Had DSSSL been the choice twenty years ago, we might not be constantly twisting in the wind for a better paradigm.


I don't use Tailwind much, but couldn't you still use the Zen Garden style of CSS with Tailwind's @apply?


You absolutely could. But most don't, because, as has already been mentioned in this thread, and explained by Adam Watham himself(1), it's not usually the appropriate thing to do. Components are usually a better abstraction than CSS classes.

1: https://adamwathan.me/css-utility-classes-and-separation-of-...


The gospel of separating styling from content comes from an era when most web sites were comprised of collections of hand crafted HTML documents, when it was a pain to make site wide changes to styling because it meant updating each of these documents by hand.

These days web sites are mostly comprised of HTML pages rendered on the fly by some type of web app which composes pages from nested templates injected with content from a database. In this scenario separating the styling from the markup gains us little, because to change the styling site wide you only have to update a few templates, not every single page that uses these templates.


Totally agree with this. It's faster to prototype with Tailwind though, if you remember the class names well.


Unfortunately, prototypes are rarely thrown away. Prototypes become production code, because code that works is usually more important than code that's clean. Cleanliness comes with refactoring.

And that's actually OK, most of the time. In some situations you have to be certain you get it right the first time, but the web encourages you to try, deploy, and fix later. It's messy and has long-term debt, but a lot of that debt rarely comes due. You might just be the one holding it when the bill comes in, and that's no fun, but people do this because on the whole the amortized cost is less.

Just don't fool yourself into thinking that this is just the prototype. Unless you have specifically allocated resources to throwing it out and starting over, acknowledge from the beginning that this is going to be production code. That way you make fewer of those "Oh, well, it's a prototype" decisions. Not zero, just fewer.


In the context of Tailwind though, the situation isn't really "that".

Tailwind allows you to "feel" like you're just quickly prototyping, without afaict compromising maintainability at all.

If you're concerned about the ability to reuse an HTML fragment and associated styles (or just a bunch of styles), they have decent docs on that: https://tailwindcss.com/docs/extracting-components/


> prototypes are rarely thrown away

Fred Brooks' admonition to plan to throw one away almost never happens. Instead more and more features are force fit onto the prototype.

For CSS/HTML, speaking of Fred Brooks, this is an essential complexity, the tension between style and content.




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

Search: