Hacker News new | past | comments | ask | show | jobs | submit login
CSS Zen Garden (csszengarden.com)
462 points by eniz 11 months ago | hide | past | favorite | 217 comments

I always thought this was funny. This was the embodiment of the original CSS philosophy, which was to "label your html elements semantically with what they ARE, and then worry about styling those in the CSS." The whole point was to get anything style related out of the HTML altogether, the HTML would just be semantic/content related.

But then Bootstrap and other CSS libraries came out, and completely inverted the philosophy back to what HTML originally looked like pre-CSS, which is that you had all of these rules you could place directly in the HTML that would directly control how the element was styled. In CSS Zen era you could look at my HTML and have no idea how I intended it to LOOK, whereas in the Bootstrap era you would look at my HTML and see "row" and "col-sm-3" and know exactly what I was going for visually.

Now people just make components and will maybe use style variables/tokens. Just funny how things change.

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


>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


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.

Because it was "the whole point" doesn't mean that it was a "good idea", especially when the web changed so much since then.

It's not necessarily a good idea to completely separate what things are and how things look. It indeed makes easier to do a complete redesign, but how often does it happen? And if it does happens, what are the chances that it actually won't require markup changes?

I find the approach by Bootstrap (or better, Tailwind) much easier to work with: compose utility classes to make up higher-level components. It still require some encapsulation of these higher-order components (with a Web Component, React Component or even just a class with @apply), but it allows much much faster development, less spaghetti styling, less cross-browser concerns and less code all around. Ultimately I code faster with less bugs and easier maintainance: I take it as a subjectively better approach.

> It's not necessarily a good idea to completely separate what things are and how things look. It indeed makes easier to do a complete redesign, but how often does it happen? And if it does happens, what are the chances that it actually won't require markup changes?

If the markup is done properly in the first place. It is incredibly easy to restyle and you typically don't to rework much markup. It just ends up working.

> but it allows much much faster development, less spaghetti styling, less cross-browser concerns and less code all around.

I have seen no evidence of this in practice. This is only true if you design is basically a skin of these frameworks. If you have anything remotely custom you end up overriding so much you might have well just started with a normalise/reset style-sheet. So for some internal application that never seen on the outside, you can use bootstrap and slap something together quick sure. However if you are actually building something with a unique it just doesn't really work.

If you think about what you are doing instead of just jumping in and coding. You can break stuff down properly without the need for hundreds of classes that typically come with these CSS frameworks. You do end up with clean CSS and the markup is clean and you do have less code.

By doing things properly i.e. you markup and css is correct. You have less cross browser bugs. I end up in my current being asked by a coworker to pick up IE bugs (yes we still support IE9 upwards). Only 10% of the fixes are actually problems with IE. 90% of the problems are correcting the markup (making it valid) and cleaning up the CSS and it just works cross browser. Sure you will have to work around things like you don't have flexbox and other niceties and you have to use an alternative style-sheet. But fixing the markup normally gets it from "not rendering properly at all" to "rendering only slightly wrong".

> I have seen no evidence of this in practice. This is only true if you design is basically a skin of these frameworks. If you have anything remotely custom you end up overriding so much you might have well just started with a normalise/reset style-sheet. So for some internal application that never seen on the outside, you can use bootstrap and slap something together quick sure. However if you are actually building something with a unique it just doesn't really work.

I had the opposite experience. I've build a few projects with Tachyons and Tailwind, and I rarely have to create custom CSS. In one of the largest ones (that actually had a 100% custom UI toolkit with over 40 widgets) we only had about 120 lines of custom CSS, pretty much just overriding colors and adding some utility classes for animations, custom drop shadows and some weird hover states.

The reason we need so little extra CSS that is that those frameworks use the same defaults that designers use: everything is a multiplier of 4px/8px, font sizes are proportional, and it follows design principles. Actually, if you work with a designer chances are most of your CSS is already very repetitive, because designers love patterns.

I've heard all this before. I am extremely sceptical and tbh I wouldn't want to build a site this way at all.

It goes against what CSS was supposed to do and generally the results are IMO hard to work with because you have the overhead of having to learn how the framework works rather than just using the fundamental principles of what you are working with. Also the markup is horrendous to read.

With modern CSS you are given so much control. Your style-sheets aren't complicated anyway.

I agree. I like CSS, and I don't like anything the frameworks offer, they're just the worst of all possible worlds: a LOT of CSS (it's not just the "custom CSS" that counts, from the perspective of the browser even off-the-shelf Bootstrap is 100% custom), with no aesthetic pleasure to show for it.

But that's for my own projects I work on as a single dev, in a team I might not mind as much. For something corporate, unless it's a corporation I can really get behind, I will not care at all, because I know it'll be thrown away soon. Let's make it bland then, I don't mind. But for my own things, it's not even a consideration.. I don't even start with a reset stylesheet, I start with a blank file, and I enjoy thinking up the overall structure just as much as I enjoy tweaking values here and there, and I still like things I made over 10 years ago. Care for the little things always ends up showing, somehow.

If you look at some talks on ideas behind oocss you can understand that a lot of elements share similar styles. It's all boxes in the end. There is this one talk about refactoring a huge pile of css into a small number of reusable visual styles, I think it was for facebook. The semantics of an element might be a comment box, but visually it's a box with a shadow and a chat box or sidebar might share the same look, thereby it would make sense to assign them the same class (classes are intended for extracting common visual styles). Doing styles the zen garden way was usually done via long selectors to target the elements and you would end up with css code that is tightly coupled to your markup. Moving html sections would cause the styles to break. Using strictly visual styles (ie functional classes) makes it easier to distinguish the style aspect from the content and HTML is already a presentational medium.

> classes are intended for extracting common visual styles

No, they’re intended to group together semantically similar elements. There’s no reason that a blue button and a blue link should be related–what if I want to make the button red later?

What about a classes like primary-color, secondary-color, danger-color & success-color?

Having two elements share the same color creates a relation between the two elements. If you have decided to use the same color for both elements it is probably because this color has a specific meaning. If the color of one of the elements changes it is probably a good idea to also change the other element.

That sounds like an excellent use case for CSS variables.

Those were not supported across all browsers for a long time (recently IE11). Also, a variable only covers one property and is not adequate to extract many shared properties. Less/sass mixins and inheritance are a good way to extract reusable parts shared between components.

If you call things what they are it works out better e.g. a class for a call to action class="btn-cta". Want a large call to action button class="btn-cta btn-large" or similar.

I really should write something on forgotten simpler CSS / JavaScript techniques.

This is exactly what Bootstrap does...

Kind of and kind of doesn’t. I am saying you should call stuff what it is. So a larger component maybe (this comment text box for example) the styling that belongs to that should all be grouped logically together. The easiest way to do this is have a element with a class attached called comment text box.

Bootstrap does this on some components but it has loads of positional bits and pieces mixed. Also the components are fairly generic.

> ...in the Bootstrap era you would look at my HTML and see "row" and "col-sm-3" and know exactly what I was going for visually.

Part of the blame for this has to fall onto the lap of CSS itself.

Up until CSS-grid it has been too damn hard to get layout to "just freaking work" with CSS.

To be fair, it was even more of a dumpster fire back in the early naughts when almost everyone just used HTML tables to do their layouts. The folks behind CSS should have caught on at that time and focused on making layout better and eliminate thousands of person-years of frontend people grinding their gears... BUT NO, not until 2018-ish did we get CSS-grid.

And ironically CSS-grid was born as part of WPF's Grid component.

Not surprising at all. The desktop application world has long enjoyed relatively fuss-free layouts. Java swing had nice layout mechanisms too. MIG-layout comes to mind.

I've seen people seriously recommend marking up your document like this:

  <div style="display: table;">
    <div style="display: table-row;">
      <div style="display: table-cell;">
How in the nine fires of hell is that better than just using a table?

Once upon a time every website layout was defined via the Table element. Your side bar would be a cell spanning multiple rows, and inside the sidebar you’d have another nested table that defined more layout. The shift to table-less divs came almost as a massive over-correction to the abuse of nested tables.

We are in similar egregious territory now days with how we’re doing styled components directly in the javascript and totally forgoing some of the principles of CSS (we are effectively in-lining styles , for everything). That’s alright, we go through this upending in frontend every 3 years anyway.

It's a bit worse than that, even. Instead of the abuse of semantic elements, you don't have semantic elements at all. It's a giant mess of div tags. We've 100% given up on accessibility on the web. We've also thrown in the towel on device-agnostic HTML as well. For all of the grand plans of the '90s and W3C, they all failed. Every. Single. One. This includes CSS, which is an abomination.

If that weren't bad enough, let's discuss the fundamental core of the web: links.

Links are dead. They are buried under a mountain of SPA walled garden jank, teased at (but never granted) on Pinterest or Quora or LinkedIn or Facebook, or out there scamming users with shortened URL services. Corporate users are subjected to annual security training lessons where they are taught never to trust links (email, text message, or otherwise) because the alternative, training users to understand domain names, is just so impractical that we have all given up. Google gave up, with Chrome. They don't even want to show a domain. It's that bad and awful.

To give you an example of how shit it all really is, I recently had to look up an issue related to a Microsoft product. A quick Google search lead me to a number of Stackoverflow and blog posts on the issue. I found a number of links, pointing to Microsoft's bug tracker (links from just a year or two ago). And here's the kicker: all the links 404. The bug tracker is simply not there anymore. This is Microsoft we're talking about. They have given up on links. They have so given up on links that they can't even be bothered to let the user know what happened to those links.

Things are significantly worse on the mobile web. I would estimate that a good 90% of the web doesn't work on mobile in any sort of way that would delight a user. It's more that users just deal with this massive pile of shit. Watch someone use a mobile web browser sometime. Watch the nonsense they have to deal with. The janky-ass scroll popup sluggish ad-infested dumpster fire. All of it.

> Watch someone use a mobile web browser sometime. Watch the nonsense they have to deal with. The janky-ass scroll popup sluggish ad-infested dumpster fire. All of it.

Hence each website tries to create their own app. Users are drawing in apps that track every move they make and batteries do not keep their charge even to make an emergency call.

NetObjects Fusion allowed you to create pixel-perfect HTML layouts before CSS using just nested tables. It was both amazing and frightening.


I remember a tool a lot like this in my teenage days (late 90's). Even then, I knew the things it was doing were horrendous...

And for what it's worth, NetObjects still exists - http://netobjects.com/

Because assistive technologies (like screen readers) won’t interpret it as a table, but the browser will, giving you the ease of table-based layouts without the accessibility hang-ups.

At least VoiceOver on Safari uses the `display` CSS property to decide how to describe an element unless you explicitly give an element a different ARIA role in the HTML, so this isn’t 100% correct in practice (although it obviously should be!). [0]

[0] https://bugs.webkit.org/show_bug.cgi?id=197786

The right way to fix that would have been to add a simple annotation that the purpose of the table was for styling, not semantics, something like:

  <table type=for-display-only ...>

Why do you consider that better? If I understand your suggestion "type=for-display-only" would semantically turn the <table> into a <div>. Why not just use a div in the first place?

Because it's DRY. With the top-level annotation, the rest of the table spec remains unchanged, so if you change your mind and decide that you really want a display table to be a semantic one or vice-versa you only have to change on thing whereas if you used DIVs you now have to change not only the top level but also every row and cell.

You don't decide on a lark if you want some content to have table semantics or not! Tags are selected to indicate the semantics of the content. Content don't change semantics unless you rewrite it to actually be something different.

In any case, you might just as well decide the table was a list item or headline then, right? So you would need

   <table what-i-actually-mean="ol">...

So two things...

First, one of the reasons HTML has been as successful and widespread as it has been is that mere mortals are able to use it, not just trained software engineers and designers. Mere mortals may not make such decisions on a lark, but they might make the decision incorrectly and have to go back and change it for that reason. Why make more work for yourself than necessary?

Second, making changes is not the only reason to make code DRY. Re-using TR and TD tags is analogous to operator overloading. If you want to add two numbers you want to be able to write x+y and have the compiler figure out whether that means an integer add, a floating point add, etc. You don't want to have to write (say) x II+ y if you want to add two integers, x FF+ y to add two floats, x LL+ y to add two longs, etc. It's the same for table rows and cells. The mental distance between tables-for-layout and tables-for-structure is smaller than the mental distance between integers and floats. It's just annoying to have to keep telling the computer over and over and over again "this is for layout" or "this is for structure" particularly in a case where the number of repetitions can be very, very large. There is no value add in forcing someone to do substantially more typing when the thing being typed contains no additional information that the system does not already have.

> It's just annoying to have to keep telling the computer over and over and over again "this is for layout" or "this is for structure" particularly in a case where the number of repetitions can be very, very large.

I have a hard time understanding this scenario. What kind of content are you working with?

What difference does that make?

I'm trying to understand the scenario you describe in the context of HTML.

If I am inside the context of a <table-for-structure> tag and I want to create a new row then the only kind of row I can create is a <table-row-for-structure>. It makes no sense to put a <table-row-for-display> inside a <table-for-structure> so requiring the programmer to specify <table-row-for-structure> rather than just <table-row> or <tr> is making her do a lot of extra typing for no value add. A <tr> inside a <table-for-structure> is necessarily a <table-row-for-structure> and a <tr> inside a <table-for-display> is necessarily a <table-row-for-display> just as a + operator operating on two integer values is an integer addition and a + operator operating on two floats is a floating point addition. There is no need to force the programmer to do extra typing to specify what is meant by + in a particular context. Likewise there is no need to force the programmer to do extra typing (or thinking) to specify what <tr> means inside a particular context.

But...you do only need to type <tr>. The problem you describe only becomes an issue if you use <table>s for layout in the first place, so just don't do that. If you want to display something (which isn't semantically a table) in a grid-like layout, you use display:table or display:grid in CSS, you don't change the markup. And vice-versa if you have <table> which you don't want to display in rows and columns, you can override the default presentation in CSS without changing the markup.

The hypothetical <table-for-layout> element is just not needed in any scenario. It would have been useful back in the day before IE supported display:table, but that is at least a decade ago.

> The problem you describe only becomes an issue if you use <table>s for layout in the first place, so just don't do that.

I could just as easily say that the "problem of overloaded operators" only becomes a problem if you try to use + to add anything other than two ints. So don't do that.

But OK, assuming I accept the premise, what should I do instead? The CSS community has been dithering about the answer for years. Only very recently has there been anything even remotely approaching an acceptable solution i.e. a solution that actually reproduces table layouts without having to pile on a ton of hacks. In the intervening years, a lot of legacy code was produced that used <table> for layout because it was the only thing that actually worked.

There also the fact that <display-table><tr><td> or something like that just looks a lot cleaner and is easier to read than <div class=table-for-display><div class=table-row-for-display><div class=table-cell-for-display>. When you make complex table layout you end up with a lot of TR and TD tags, so it makes sense to keep those short to avoid cluttering things up.

If you genuinely want a layout exactly like a html table you use display:table. You probably don't, but it is there if you want.

You don't really need repeated class=table-row-for-display etc, this can be achieved by CSS contextual selectors.

But in reality html tables was not designed as an all-round layout tool in the first place and the layout algorithm was never specified in detail. Flexbox and flexgrid are typically more appropriate and powerful as layout tools.

> display:table

I tried that once many years ago. It didn't work. It might work today but I no longer care.

> this can be achieved by CSS contextual selectors

That would be true if display:table worked, but it doesn't (or at least it didn't) and so it doesn't.

And you still need some markup for the contextual selectors to work on. The obvious choice is <table><tr><td>, or, if it existed, <display-table><tr><td>. Maybe <grid><gr><gd> but that's not going to happen.

> That would be true if display:table worked, but it doesn't (or at least it didn't) and so it doesn't.

Can you describe the problem you are having?

No. That last time I tried it was many years ago. Maybe it works now. I neither know nor care.

So you are basically just trolling at this point.

No, I'm giving you honest answers to your questions. Just because I have not gone back to explore a broken feature to see if it is no longer broken doesn't make me a troll.

But my point stands even if display:table works nowadays. The problem is not what you have to type in order to specify that some piece of markup should be displayed as a table even though it is not semantically a table. What matters is how much you have to type, and whether you have to redundantly specify that a table is for display only on every row and cell. To use display:table you also have to specify display:table-row and display:table-cell, and you have to do it again and again and again and again even though all this information is redundant and only needs to be specified once at the top level. There is absolutely no rational justification for this. It would be as if you had to specify the type of a variable in C not just when it was declared, but again every single time you referenced it.

You can do this already with ARIA attributes:

<table role="presentation" ...>

[edit] See https://www.w3.org/TR/wai-aria-practices-1.1/#presentation_r... for details

A11y hang-ups? It's a benefit that it makes it less accessible? That doesn't make any sense to me at all.

You have it the wrong way round, it's a benefit that it makes it more accessible.

Abled people benefit from a system where their browser considers that div as "table-like" in the way content flows through it. Likewise, disabled people benefit from the fact that their screen-readers consider the div as a simple container without imparting any sort of tabular semantics ie expecting some data organized in rows and columns.

I think they mean to say that sometimes you might want the visual structure of a table but you don't necessarily want it announced as a table via screen readers since it isn't data that's being represented.

This is straight out of the CSS renaissance: There used to be a world, where the only sensible way to get something look a certain way on the web was using tables. But since using the actual table element, for anyone who cared about html semantics and accessibility, was a no go, assigning "display: table" to a non-semantic element was the next best option (or rather the least bad).

It will not surprise you to learn that this concept was not exactly well understood (to be fair, most things were not well understood, including js) and people started building all sorts of actual data tables out of divs with "display: table" applied, because apparently that's how you were supposed to do it.

Nowadays this is obsolete, of course, mostly thanks to flexbox but also grid.

This makes me cringe. I may have been 12 but I was making websites in 1998. And they were decent--I mean, it was a lot of right click > view source copying. But I fell in love with the Web Standards movement. I was probably the only 13 year old whose book shelf included books on perl, css, xml, and the like.

I feel the same way. It's probably because I'm 90s kid and nostalgia, but I wish web standards were taken seriously.

Ah yes. I saw this happen in the mid-2000s during the backlash against tables. You see, some visionaries had realised that the table element in html was being abused to create layout. The tools to do layout were added to css instead and the advice was to stop using tables for layout. Simple enough. But during these times there are always people who don't get the original message, or don't understand it, and just start blindly following some derivative of the original advice. That advice was "use divs". So they did. They would look at an html source and if they saw "table" they would turn their nose up but if they saw "div" they would rejoice.

The irony is it was completely against the original intention which is to use html to give semantic meaning to elements. Tabular data doesn't just have a visual layout, it is rows and columns. Most people still don't understand this today although with things like markdown people are doing it even if they don't realise (unless they start embedding html/css, of course).

There were a lot of grid base frameworks which did this. Foundation 5 was unique in that it still used these rows, but you uses scss to assign those attributes to your elements. Your pre-compiled CSS looked clean and your HTML looked clean and your final CSS was a minified blob of crap you tried not to thing about.

Really CSS Grid does the same thing; there's just more in CSS now and it's a whole lot cleaner.

Aside from what people said about screen readers (which at least makes it a bit better than tables) this is still a bad layout.

Here[1] is a revised edition of a book I read in 2006 about this topic how people often just replace all table elements with div elements and call it a day instead of using all the options CSS provides. Another topic was using all the tools the browsers with the best standard support gave you while still providing a more limited, but at least usable, version for browsers which hadn't implemented some features (yet). Even back then you could make pages which read well if CSS wasn't available and were visually appealing with CSS applied and today almost any browser has all these tools available.

[1] https://stuffandnonsense.co.uk/transcending-css-revisited - there's a free online version available

Depends - if the content isn't semantically a table (data points with a two-dimensional relationship) but you just want a table-like presentation and you want to conform to accessibility guidelines, this might be totally fine.

Sure it might be more elegant to do it with a stylesheet, but for a one-off situation it is not that bad.

There is a persistent attitude that presentational information in the markup is Bad and Evil. This is only partially true.

Misusing semantic html elements (like using <table> for purely layout purposes) is bad because it hurts accessibility for other people. But putting CSS directly in the HTML does not hurt anybody but yourself. If you do it all over the place it becomes a mess to maintain, but in particular cases it might be the simplest solution.

Probably to avoid the dumb limitations on having forms within a table? Still an awful and ugly way to do it

I am convinced that people who recommend things like that have no idea where we are or how we got here.

Something about accessibility and screen readers that people virtue signal about, but never actually test for.

CSS Zen Garden seemed to have a message that you don’t need tables for everything, but it was astonishing how few of the featured designs ever handled responsive layout properly. Getting text to fit into a rectangle by cheating was very common and you’d see bleed everywhere at a different resolution.

Until flexbox, there was no way to fix this without resorting to table cell behavior. It ultimately soured me on the Garden. And thankfully I got to use CSS3 shortly after.

Keep in mind Zen Garden was written WAAAAAAAAY before mobile layouts were a thing. Back then, you had mobile sites .. for people with PalmOS, BlackBerry or flip phones with tiny browsers. I think my edition of this book came out before the first iPhone (I remember owning it when the girl behind me at work got the original iPhone EDGE), so responsive design wasn't a thing (I don't think media queries even existed in the CSS standard, or if they were, few were using them yet).

Heck, when the Zen Garden was first released, you couldn't even browse the web on a Blackberry. 1024x768 monitors were a luxury. 760px wide was all you could count on for a browser window once you accounted for window edges and scrollbars on the average user's 800x600 monitor (a few years later as 1024px monitors became more common, a 960px site width became the standard); and I had co-workers who were still getting by with 640x480.

I was fighting my coworkers with 1440 monitors to make sure we still worked on 768 width (plenty for 800px + scrollbar, or portrait on the brand new iPad). UI people like to maximize negative space in their mockups and it's not uncommon for them to use extremely short example text to emphasize that effect. Like how your living room looked so big until you put all of your crap into it.

And the thing is, even if you had a 16XX monitor, who wants to maximize a tool that you might be transcribing data in or out of? I might actually need two windows side by side to facilitate that work.

I was pitching responsive (or at least, fluid) design by 2011, and I was not blazing trails. I started using the iPad as an example but tiny laptops were an issue, and in a business setting, most production projectors were only 1024 pixels, hardly anyone had the 1280s, and the cheap ones were 800x600 native with terrible interpolation.

Wikipedia has this timeline:

> Cameron Adams created a demonstration in 2004 that is still online.[46] By 2008, a number of related terms such as "flexible", "liquid",[47] "fluid", and "elastic" were being used to describe layouts. CSS3 media queries were almost ready for prime time in late 2008/early 2009.[48] Ethan Marcotte coined the term responsive web design[49] (RWD)—and defined it to mean fluid grid/ flexible images/ media queries—in a May 2010 article in A List Apart.[2] He described the theory and practice of responsive web design in his brief 2011 book titled Responsive Web Design. Responsive design was listed as #2 in Top Web Design Trends for 2012 by .net magazine after progressive enhancement at #1.

And while the Garden was indeed around long before that, IMO it didn’t get properly cool until maybe ‘07. And once fluid and responsive came in it wasn’t keeping up.

The point, I thought, was to be able to send people there to learn, and I was afraid of having to fix that kind of smoke and mirrors in our production code so I stopped telling people about it, other than other seasoned UI people fora particular design, and half the time it was to laugh at one, not learn from it.

> IMO it didn’t get properly cool until maybe ‘07

Wikipedia says the book came out in 2005, which if I remember correctly had plenty of colour pics inside. You don't get that kind of tech book unless you're already properly cool.

Responsive design was absolutely a thing, because the web was responsive from the start. It was CSS that made it non-responsive; sites that used tables for layout reflowed properly on PDAs or phones, and still do.

Virtually every CSS Zengarden site was filled with exact pixel counts and page offsets. As an art project it was neat, but practically speaking it was a disaster.

When I was first learning CSS I was trying to replicate a very easy 3 column layout where the middle column would grow and shrink with the screen and consist of multiple variable sized elements arranged neatly in a column. What should have been one of the most basic layout styles turned out to be quite a challenge to achieve with CSS. I wasn't even trying to have anything fancy like columns that disappear on super narrow screens. Just the most basic three column layout that didn't leave wasted space on the page. In my struggle to get it to work I went to sites like CSS Zengarden to figure out how they did it and was extremely disappointed to discover that they hadn't found the solution either. My thought was it couldn't be difficult because it was so easy to do with tables and literally everybody online was telling me that tables for layout were completely surpassed by CSS. Plus I was working with CSS 2, so any glaring deficiencies like this from CSS 1 would have definitely been fixed by then. I mean this was the point of CSS right? To do layout?

Ah, the three column layout with equal heights, the holy grail.*


One of my big coups was fixing the reflow on our multicolumn layout. The page I fixed it on was survivable as it was, but a whole third of our UI would not have worked at all without it.

The first time I got to use flexbox in production (different project) I was happy as a pig in shit.

Even with "display: table" or flexbox you couldn't do something as simple as colspan.

Oh man, I had blotted that out. There’s a somewhat arcane set of table styles that will give you proportional layout of blocks that is more powerful than colspan. I found that it was often worth the trouble of reaching for the more sophisticated solution.

I've long thought about this too. Eventually I've come to the conclusion that CSS Zen Garden was more about "Hey you can do all of this with pure CSS" than it was "You should do it this way". At the time that I discovered Zen Garden, CSS was in it's more early, primitive days. As a front-end developer, it was easy to say "I can't achieve this design without changing the HTML Structure". Zen Garden showed us that this was just an excuse, (just about) any design could be achieved without a requirement to fundamentally change the HTML of the page. It was eye-opening to see some of the ways theme authors rearranged content, broke down those box boundaries, and used design tricks that stretched the limits of CSS and HTML in that era.

It was awfully inspiring, and I think the point was never - "this is the way you should encode pages" it was more about taking excuses away.

The point absolutely was "this is the way you should encode pages", or rather "this is what is possible if you encode pages this way". The purpose of Zen Garden was to highlight the separation between style and content; that separation is why we've got CSS as a separate language to HTML in the first place.

No, it was absolutely about the way you should "encode" your pages. I would choose the word "markup" here instead as that's what it is, but it was 100% a recommendation on the benefits of separation between markup and presentation.

Or, was it to prove that yes, you can live without Flash.

People are far too concerned with these things anyway, IMO. All ways work well enough and perhaps I'm just ignorant, but in the past 25 years I haven't seen a single good example of a situation where someone won against the competition because of better presentation or better choice of frontend framework. That excludes those who shot themselves in the foot with Flash though.

IOW, put the effort into backends / core functionality and not elegant styling or elaborate frameworks.

I think this reversal is sad, actually. Even sadder, that one of the driving reasons was people just giving up on CSS ("too complex/weird") and going for spaghetti and a wall approach. Then trying to use tools to plug the knowledge hole.

Honestly I say the reason it’s sad is because of the idea that CSS promised something it couldn’t deliver. The sad part isn’t that people gave up on CSS, the sad part is that people believed it could work this way in the first place.

Writing CSS stylesheets by hand is like writing HTML pages by hand. It just doesn’t scale, and you run into a million tiny problems every time you change something in a medium size project. So for HTML we use templates and components. For CSS, we want the CSS for a component right next to the component itself in our VS Code window, so that actual humans have good insight into what styles will affect a particular component. The alternative—keeping the CSS separate—requires its own set of tooling to plug the holes, like all those fancy web developer tools built into browsers these days.

I always thought the approach of returning XML from your web server and having it refer to an XSLT stylesheet made the most sense. Unfortunately, XSLT is a very verbose and clunky style language. If it had been a better language, I think it could have been a good solution.

I think component systems like React are the closest we have to achieving that dream. This is why Vue, React, Angular etc. all look something like writing your own tags and then implementing them in terms of, eventually, standard HTML tags.

You can even swap out the web browser front-end, to an extent. I know that some mobile apps are done this way.

It is only sad when you have not worked on a medium sized website/webapp.

For a small document like css zen garden where the goal is to produce a diversity of design without changing the html? css selectors are perfect. But how often is that the goal of the UI team?

The goal of a ui team is to have a consistent ui that is easy to change. Components helps with consistency. It also helps in separation of concerns: you can have someone writing the component library and someone else using it.

The goal of a ui team is also to minimise the amount of ui bugs, and the amount of ui code. If you let people go wild with css selectors, you end up with badly scoped class names and very painful integration phases where selectors breaks the ui across the whole application. When fixing bugs people are too afraid to remove anything because it means that they have to test a huge scope.

The trend I see is not spaguetti (except in places that don't care). It is the use of a very restricted type of selector: .class_name. Some people use css BEM or functional css and write those names themselves. Some people use a css in js library that generates them.

We have started adopting css BEM two years ago and now we are considering using a css in js library. I had to manage a css library update recently and 90% of the issues were in place where people didn't have this kind of methodologies.

Just like with programming you have to limit scope. And avoid using global scope. Its fine to have a "private" base style for components. The power of CSS however is that users can overrule those styles. Its however important to organize the css in a cascade and not have rules for the same element spread out all over the place with !important everywhere.

You used to see CSS frequently used by hobbyists making personal websites. As a result, you'd see a lot of posts about what cool stuff they could create, their opinions on how to structure things, semantics, etc.

Now these same people are mostly doing it for the paycheck. And there are a lot of new people doing it as well. In fact, dozens or hundreds of authors may be maintaining the same stylesheets. You just have to get your changes in.

People get older, begin to care less. The web has surrendered to commercial platforms. It's not as exciting.

Even with the most powerful CSS methods, you simply cannot completely separate the structure of the HTML from the layouting.

It's better to give up on this ideal right from the beginning than to build something that ends up getting complicated with work-arounds and edge-cases.

For awhile now I've felt that the CSS libraries like Bootstrap, Semantic UI, etc are never the "right" way to organize your markup and CSS for a large project. They're great for getting out something quick and dirty that looks decent. But once your project passes a certain scale (in size or time spent maintaining it), the balance shifts in favor of semantic markup and style in CSS using BEM or something similar as an organizational paradigm. The latter just doesn't seem conducive to off-the-shelf styles because semantic organization is different for every project.

Another way of thinking about it is that CSS libraries build infrastructure for universal reusable widgets. In the beginning of a project it makes sense to build your app by putting together these building blocks. But as time goes by and the app grows, you start to develop a layer of higher level UI abstractions that are specific to the domain of your app. And when that happens it is often in conjunction with some kind of a re-styling and the old universal building blocks are no longer what you want. I've seen multiple large frontend projects go through these phases, and am starting to see them as a natural evolution of frontend projects.

Well I think it went that way because CSS is lot of frustration and not much zen.

> whereas in the Bootstrap era you would look at my HTML and see "row" and "col-sm-3" and know exactly what I was going for visually.

say what you will about utility classes, but the grid classes are absolutely necessary, especially when many elements might need specific behavior for different screen sizes and must interact gracefully. without the grid classes your css would be an absolute nightmare of a thousand often-nonsensical "semantic" classnames littered with a crapload of fragile media queries.

This is no longer true with CSS Grids. The grids are all defined in the CSS itself, allowing us to once again separate style and content, as well as allowing us to define custom templates for different screen sizes (rather than simply force them into a single-column, left-to-right order).

I know this is still barely being used, but it's clearly the better way to go.

Sass removes most of the cruft. I made a semantic flex grid many years ago, and the result was a lot more clean than using utilities, even in the css side [0]. This was before CSS Grid Layout was widely supported, nowadays you can use plain CSS grids and get similar results.

[0] https://github.com/nitely/semantic-flex-grid/

> I made a semantic flex grid many years ago, and the result was a lot more clean than using utilities

your grid has zero media queries in it, which means whatever grid classes you were using before were not responsive - which is where 90% of the complexity lives.

complex/nested responsive grids are not simple, unfortunately. i've made one, too: https://github.com/leeoniya/flecks

> complex/nested responsive grids are not simple, unfortunately.

How does utilities make complex/nested responsive grid simple, again? I'm arguing semantic css is simpler than using utilities all over the HTML, not that it magically makes responsive design easy.

> your grid has zero media queries in it, which means whatever grid classes you were using before were not responsive - which is where 90% of the complexity lives.

There are some in the examples [0][1]. Both for responsive design and nested grid, sadly not for both at the same time. It's not much more complex, though, well I guess it depends on how complex are we talking about. Anyway, CSS Grid makes semantic layout a lot simpler now.

[0] https://github.com/nitely/semantic-flex-grid/blob/gh-pages/s...

[1] https://nitely.github.io/semantic-flex-grid/

<handgrenade>tables handle grids quite nicely</handgrenade>

Bootstrap still gives me an eye twitch. It didn’t handle color customization properly until at least 3.0 (oh you could color many things, but you want light text on a dark background and you’ll have to override a ton of stuff).

I was ordered to use a version that didn’t even handle responsive design properly. Right after we had agreed to make the app responsive.

It's a shame that Foundation never caught on fire because they were/are way ahead of Bootstrap in these and other areas.

To "become popular" is just "caught on", not "caught on fire".


Because every 10 years you have people who haven't been around for the past 20 years (re-?) inventing things.

Personally, I find the mixes of class names like with Tailwind really confusing and need to keep looking it up when using it. Doesn't really make things easier imho

So long as structure and design overlap there will always be some inescapable coupling. The choice is deciding which one should master over the other.

Funnily enough, styled-components in React does allow me to focus on the semantics meaning without worrying about the style.

http://smacss.com tried to push this, but failed

Can’t remember which, but there was someone who made a CSS library that patterned like a fluent interface.

They had lots of selectors that were adjectives, and most of them composed. So you could have a class=“tiny button” or whatnot.

Perhaps Semantic UI?

YES. That's the one. Thanks.

And now we're back to table-based design and flash-like but less powerful javascript based application.

It's a failed experiment. We've had over a decade of people trying to use CSS to style websites and ending up with worse results than if they'd just changed the HTML.

Let it die.

Semantic HTML has never been something that businesses asked for. HTML has never been a good format for structured data.

Things have simply moved towards what's actually manageable in a production environment, not what some ivory tower designer thought was good practice.

This approach is extremely seductive because on the surface it sounds so "pure" and "clean" but the reality is that on large projects it leads to some of the most horrific, hard to maintain CSS you'll ever see, no matter how hard you try to keep things in good shape. CSS is just inherently more difficult to maintain than HTML, and choosing a workflow that encourages editing CSS instead of HTML just makes things harder and harder over time.

Choosing an approach where CSS is treated like a third-party dependency that is _consumed_ by your HTML ends up being much more practical, maintainable, and scalable because editing and maintaining HTML is _easy_ — every time you change a class on an HTML element your changes are local and predictable.

Always thought this article by Nicolas Gallagher did the best job arguing this point:


CSS Zen Garden is from a time when people still used tables and font tags to design their pages, and as such it was a pretty powerfull way to convince people there are better and more efficient ways to do things.

I think the important part here is "efficient". It is more efficient to go to a style sheet and change a color instead of 1000 font tags, but in other ways it's just more efficient and easier to adjust your template-generated html and be done with it. Or write it from scratch.

The thing that I think doesn't work very well with this way is reusability. Rarely do you have this one thing you've made, and that you can use in the completely same way in another place. So you end up adjusting the style through CSS for a specific case, which eventually results in having rules like .foo > .bar:not(.baz) :first-child and making a change there results in playing whack-a-mole: you change something, break it in another place, fix it there, now it breaks in the third place etc. This is even worse if you have multiple people doing quick fixes.

There are other reasons too, but in general all of that is fine if you want to do a one-off thing to see if it could be done. Especially if you're a designer writing the code yourself. But getting a finished design from somebody who doesn't care about code is different because you cannot really predict what people will think of -- and I've actually never seen anybody do a redesign like this.

I think the approach can work really well for web pages that are meant to be documents, but no so well for web applications.

But can you do what CSS Zen Garden does only by changing HTML? If you can't, it means you failed at separating concerns.

Additionally, applications that you need to customize/theme usually makes it hard for us to edit the HTML. The only option is to edit the CSS. In this case, you whole argument breaks down.

p.s.: In your case, I believe Tailwind should be pushing more for the use of @apply, instead of making those god-awful markups :(

> But can you do what CSS Zen Garden does only by changing HTML?

Yes of course you can, if you can change the HTML you can build an entirely different website, and you don't have to change the CSS at all because with something like Tailwind it's a "universal stylesheet".

You'd still need to write some custom CSS depending on the design you want to achieve, though. So, you're finally not only changing just the HTML.

Not true at all. You can build two sites that look completely different without changing the CSS at all if the API of the CSS framework is low level enough, like Tailwind, Tachyons, etc.

Agreed. I was a big proponent of the csszengarden way of developing sites. Then during the development of my latest site [0], I decided to use bootstrap for styling. And now I am really liking it. Makes things much easier, at least for me. [0] https://embit.ca

I recently brought this up with my team. As an "old-school" web developer, I buy in to the whole CSS as design thing, while the front-end engineers @ work switched to using styled react components. As we look to make substantive design changes, now we have multiple places to make the CSS changes, only now it's the SASS project and all of the React components / projects. I must be missing something about how hip and cool styled components are, but they'll never be as cool as the CSS Zen Garden :)

I think different parts of the page need to be treated differently.

In a typical webpage, you'll have lots of "chrome" (menubars, sidebars, footers, logos, etc.) and "content well" of some sort. For the content well, the content is probably going to come in through some sort of CMS with Rich Text Editor that can handle bold, italics, links, headers, blockquotes, etc. by outputting plain HTML.

The content well should be designed to work without classes on the items. It should be able to take the <a href> and <em> tags and make it look correct. The tags themselves have a semantic meaning, and you can imagine this same content surviving through multiple redesigns of the site.

But for the chrome HTML, the tags are only there as part of the current design. When you redesign the site, there's no reason to expect the same tags to be used. It may or may not be possible depending on the goals of the redesign, but either way, it's not a goal, the way that reusing the content well HTML is.

I think this is what leads to the disconnect. If you're new school web dev making CSS-in-JS components or whatever, you're expecting your components to be thrown out when a new design comes along in five years. If you're designing the content well, you expect the HTML to live essentially forever or at least as long as the business.

Well said

I also started coding when CSS Zen Garden was the best thing ever but sorry, CSS in JS is better.

With classes and a separate stylesheets, there are no statically analyzable connections between them. You typo a class name? Too bad. You're no longer using that class anywhere? No compiler will tell you it's dead code. You want to increase the padding in this one place? There's no way to be confident what else it will affect.

And all the "benefits" that stylesheets tout are also offered by components. No one is adding <font> tags on all on all of their headings. With components, you just set the font once on the heading component.

Same, started doing frontend back in the CSS Zen Garden days, and CSS-in-JS has been a godsend. Having the tooling do static analysis on your components and their corresponding styles has made life so much easier. Reference a color that doesn't exist? Error. Reference a component that doesn't exist? Error. etc...

Also, in response to GP: CSS-in-JS does not take away the ability to roll out global CSS changes without updating individual components. It actually gives you more tools to easily share styling across components.

> No one is adding <font> tags on all on all of their headings.

Ok? I'm not sure the official documentation is encouraging factoring out things like font styles to a central place, so you for example easily change the look from serif to sans, or adopt a signature font?

Am I missing something?


The original argument for CSS from 20 years ago was:

Instead of saying: `<font size="20"><b>Some heading</b></font>` 100 times, CSS proponents would tell you to just write `<h2>Some heading</h2>` 100 times with styles defined separately as `h2 { font-size: 20pt; font-weight: bold; }` so if you need to change it to 22pt, you can make one change instead of 100.

Components give the same benefit. Just write `<Heading>Some Heading</Heading>` 100 times with the definition `function Heading(props) { return <h2 style={{fontSize: 20pt; fontWeight: bold}}>{props.children}</h2>; }`. If you need to update it to 22pt, it's still just one change; not 100.

* replace `style=` syntax with your CSS-in-JS framework of choice for better performance.

Right, but in the example linked from the official docs, the css/style is in the component. So you need to change all your comp, rather than the body font style?

(obviously you can mix and match, it just seems that the official documentation/sentiment is towards self contained components that don't support page/application level theming/styling)

You're subscribing to the notion that it's good to put all your styles for all components in one file. Since the invention of variables, that is wrong.

Theming is no longer a valid argument for centralized style sheets. If you declare one central set of variables for, eg., colours or fonts, then you can still do "application level theming" (changing those colours/fonts in one place), without having to mash all the styles for every element in the entire app together in one file.

The advantage of using JS variables to represent this is you can easily ask your IDE to "find all references" to that variable. It's much easier for humans than reasoning about CSS inheritance and the cascade.

CSS Zen Garden was a treasure back in the day, one of the most inspirational CSS sites showing the power and flexibility that can be achieved with CSS over semantic HTML.

I still remember the original design from Dave Shea fondly:


One of my quixotic personal projects was reproducing this design for my Myspace profile.

Ha, I found the blog I was keeping:


It includes a small screenshot.

Yes! This brings back memories! This site inspired me to learn CSS. I was doing free Xanga themes in high school, lol.

I used to love it but know I can't help to notice that there is no max width and the font is way too small.

I remember this blowing my <table>-addled brain in 2003. This site was what convinced me to really dig into CSS, and not just use a few inline styles as hacks. This also opened my mind to JavaScript at the same time (as I looked into "DHTML"). It was a pretty different web back then!

I'm amused at how I glanced at your comment and my mind sort of yelled "hey, that opening tag never gets closed! that's going to invalidate everyone else's comments below by making them part of that element!".

Maybe I'll say </table> here just in case. :-)

This is the same for me. When you came from a table based design approach, it was hard to know how powerful CSS was. This was to prove that an help developers overcome their fear. I loved this site!

I cannot believe it's been 15 years, literally half my life, since I got my design accepted at CSSZenGarden: http://www.csszengarden.com/185/

Incredible, I had never thought of how long it's been...

I remember seeing your design back around 2009 when I was taking my first web “publishing” courses! What a trip down memory lane

It funny that colored scrollbars work again and in Firefox :)


This is my Zen Garden attempt. According to the HTTP headers it is from 20 October 2008.

You can see how font rendering has changed over the years. When I wrote this all columns were the same height and alignment cross browser.

It looks great. Nice job. I miss the web from this era. Sites looked so much more unique. People posted to their own sites and syndicated content. Feed readers were useful. Sigh.

Wow, what a blast from the past!! This was a great source of inspiration back in the day.

If you're not familiar with the project, I suggest checking out the Wikipedia article:


Ah so many memories. This was my favorite:


Dave Shea mentioned that it was no longer relevant back in 2013.


“This video is unavailable.”

Some time ago I made https://github.com/fiatjaf/classless, a framework for making themes for simple websites (like blogs) using the same basic HTML structure.

The idea is: you write HTML that conforms to the structure, then you can reuse any of the themes by just including a CSS file (and sometimes a JS file) in your <head>.

Turns out I wasn't the best person indicated to push this, as my design skills weren't marvelous, but I still think it was a good idea. There are 17 themes available, mostly ported from other places. A playground where you can see the themes (and test your own, if you are feeling like building one) is available at https://classless.alhur.es/

I wrote my blog's HTML[0] semantically, and I'm glad I did. I have a different style when someone fires up a new instance. I was already going for a retro "vaporwave" aesthetic there, and that recent Windows 93 post[2] pushed me over the edge. I apply those styles to my main site as an Easter egg when you view it in the Japanese locale.[1]

[0] https://theandrewbailey.com/

[1] https://theandrewbailey.com/?lang=ja

[2] https://news.ycombinator.com/item?id=22463415

Semantic HTML also happens to work quite well on even the most anemic browsers! I am somewhat proud that a non-HTTPS version of my website (which is designed for modern browsers) is navigable and fairly usable on the original WorldWideWeb, aside from some of the <head> content poking through.

Dave Shea (CSS Zen Garden), Eric Meyer, Jeffrey Zeldman (A List Apart), Jeremy Keith (DOM Scripting), and others who escape me provided the foundation for the CS classes I taught 15 years ago. Thanks guys!

Honestly, these designs are so refreshing. There is no place for ads. No popups asking to subscribe to their newsletter. No breaking because I have Javascript disabled.

Looking through some of the designs made me happy... and a bit nostalgic. :)

Good memories from 10 years ago (the site looks practically unchanged since then). Incredibly how the frontend nonsense of recent years allowed us to go backward. Same result but slower and more complex without any good reason.

I truly believe this is still the way to go if you want to have any hopes of keeping your HTML/CSS maintainable and easily customizable.

Seeing this page brings back memories: http://www.csszengarden.com/001/

I'm happy that this is still online.

Separation of html and css can still be a useful paradigm and does not have to be incompatible with separating your code into components.

For medium-sized projects, I have found it useful to have general (or "base" and "cosmetic" a la MCSS) styling in a central place with all my variables. For my components, I strive to balance the "structure-" and "container-" -like (similar to OOCS) styling they need while not trying to make them so general that they are over-engineered. To that end, I am comfortable enough using the central variables within my components and even some central classes, recognizing that when I do want to re-use my components across projects there is occasionally ad-hoc refactoring/customization.

Also, Css in JS is only one way of building components. You can keep your component-specific css separate from the rest without using JS.

Cool. XML, by way of HTML was always designed to be layered. As in, a layer for a different use case. At the lowest layer, is the data. Each layer used to decorate the layer below it enables using it for different use cases. CSS is just another decoration to create another layer used for another use case (styling the data for the rendering in a browser use case). While keeping the underlying data still usable for a totally different use case. CSS Zen Garden is such a fantastic showcase of that layering architecture of HTML.

Regarding Javascript applications, I consider it just another case where we're using the design of the web for something it's inventors could never foresee. Well, they did foresee "apps", but I'm just not sure React, Angular, Ember, etc. apps was what they were imagining.

I see a lot of people bickering here in the comments about what's better and why, but does it really matter? I mean I don't care if you like to wear rain boots when it's sunny or flip flops when it's raining, as long as you have some footwear on.

There's many ways a webpage could be programmed/designed/developed/styled but the only thing that really matters is that it's usable and visible to the end-user. No programmer likes every other programmers code when they have to work with it and we all know there's ten different ways to solve the same problem so just let people do it the way they know how as long as you can use/view it with no major issues who cares.

I use to own this physical book!!! .. years and years ago (I think around 2008 or 2009). I cite it as my inspiration for a lot of my early designs:


It might seem dated, but the ideas of using images and flowing layout shaped that era, and the simplicity can still be applied today (although we can make it look a lot better and cleaner thanks to CSS grid, flexboxes and other new tech that's now available in most browsers).

There's a lot of good nostalgia here if you go through their older designs.

I really like CSS Zen Garden and it had a profound impact of how I think about front-end work. I see a lot of back-end developers trying to force the markup and their styling to conform to what they want.

If you understand how the document flows, separate your CSS from your markup, write clean and valid markup and keep everything as minimal as possible. There is really a "zen" like element to it which I think is kinda lost today.

However when it comes to code I am a minimalist and tend to do as much as possible with Vanilla JS.

Encoding page layout in text is a bad idea, and CSS is a bad implementation of that idea.

What could be better, you ask? Open up Google Slides. You can make a slide that looks the way you want it. The learning curve is nonexistent. Then you can share it online and it will look okay to anyone on any size screen. There's no reason why building websites should be a hundred times harder than that.

This does not come close to the Web's design goals.

I was a huge fan of the CSS Zen Garden, and was so excited to have my submission accepted back in 2006 (#106!) when I was first starting out.

Generally, it was a great demonstration of CSS at a time when CSS was rather novel, and the "separation of content and presentation" sticks with me today, and forms a good foundation for things like built-once responsive web design.

For me personally, I met a lot of interesting people through CSSZG, including Bill Zeller (RIP[1]) and others.

[1] https://news.ycombinator.com/item?id=2074109

Still love the retro theater design - so fun: http://www.csszengarden.com/202/

Would be nice if the designs would display the date when they were created.

Digging around in the source code and on the sites of the designers, it seems they have stopped adding entries around 2013.

I wonder why.

From Dave's current site:


Hehe, I remember impressing my Web Development Professor 11-12 years ago by using CSS designs based off this website.

I am still impressed by the beauty of some of the designs.

My immediate response, as someone who does not know css that well and is trying to learn, is to open developer tools, choose responsive design mode and then iPhone 6. Only looking at the top four, none of these are that great. Where is a way to navigate? They don't seem to be using vw which I expected. Are there good examples that work well with responsive, provide navigation and don't use horizontal scrolling.

The site predates smartphones by maybe five years. Mobile friendly wasn't a thing yet.

I enjoyed browsing CSS Zen Garden and read Eric Meyer's CSS articles when I was still in school 15 years ago. Time flies and so as Front-end stack.

oh nice to see this on the web again! i recently remade this with modern web technologies - Svelte, Monaco, and serverless functions to pull things from GitHub Gists: https://github.com/sw-yx/svelte-zen-garden

I love this site. I used this site back then to learn all about HTML and CSS and the fact that it still works with those age-old designs is a testament to the original CSS philosophy.

I love this site and visit from time to time. It reminds me of a time when you thought of web design as art. Now it feels like playing with building blocks.

I've always enjoyed this site. I see that they post updates here fairly regularly.

All those who repainted their pages in dark mode should take lessons from "Steel".

Not all fonts are readable when displayed white-on-black, and some seem to forget about that.

Also this is something that's being slowly undone by ideas like Styled Components and Tailwind. My take is that those two are a step back.

The zenist of css designs for this web page is:

body { max-width: 800px; }

Done. Now go do nothing.

this era broke me as a web designer. Dom walking etc. i need to get back into current trends so this discussion is useful.

A story like this being at the top of HN is how we know covid-19 is serious.

aaaahhh good old and amazing CSS Zen Garden!!!

Why is this the top post of the front page? Is there a front-end dev that didn't see this when they were 15? Sure it's a nice demonstration of CSS but...

This gets posted every few months and the HN crowd loves it. Somehow all the technical geniuses here are still mesmerized by CSS from 20 years ago. Learning all the nuances of the Rust borrow checker doesn't leave any room for much else, except for HTML tables, that stuff got embedded too deep. Set a reminder, it's an easy way to reap the sweet karma.

Well said. I just wish the Zen Garden would put a big banner at the top that says "the cascade turned out to be a terrible idea, now all CSS is JS, and it's scoped to the component using exclusively single-class-selectors with non-deterministic names."

I see quaint selectors like `#main aside .wrapper .design-selection` and just hope jr devs aren't trying to emulate them.

People who were older than 15 when it launched?

Many of us are either young, not front end devs, or both!

According to Wikipedia, when this launched I was about four years old. It’s new to me!

At the age of fifteen I didn't yet even have an internet connection.


> I try not to make fun of people for admitting they don't know things. Because for each thing "everyone knows" by the time they're adults, every day there are, on average, 10,000 people in the US hearing about it for the first time. Fraction who have heard of it at birth = 0% Fraction who have heard of it by 30 ~= 100% US birth rate ~= 4,000,000 year Number hearing about it for the first time ~= 10,000 day If I make fun of people, I train them not to tell me when they have those moments. And I miss out on the fun. Person #1, about to have a messy fun time: "Diet coke and mentos thing"? What's that? Person #2, in a delightfully pro-knowledge mood: Oh man! come on, we're going to the grocery store. Person #1: Why? Person #2: You're one of today's lucky 10,000. {{Title text: Saying 'what kind of an idiot doesn't know about the Yellowstone supervolcano' is so much more boring than telling someone about the Yellowstone supervolcano for the first time.}}

I'd have known what xkcd it is, no pasting necessary. It doesn't apply every time someone calls something old. I'm not making fun of anyone.

The other leading HN headlines are:

* GitHub shuts off access to Aurelia repository

* NASA to launch 247 petabytes of data into AWS

* Covid-19 Interactive Model

plus we get the old CSS site from 2003...

Applications are open for YC Summer 2021

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