CSS Zen Garden
123 comments
·April 27, 2025JimDabell
radicalbyte
The reason we used tables was because getting things right in CSS in the early days across all of the browsers was a nightmare. An expensive nightmare. Which was fine if you were a well funded startup and could afford to rebuild your HTML regularly.
suspended_state
CSS at the time was still a leaky abstraction: in order to get things working, you had to include extraneous DIVs in the HTML code as anchors for the CSS rules. The standard body has attempted to address this issue with pseudo-elements and pseudo-classes as well as other features I may not be aware of.
At least though, these extra DIVs weren't disrupting the page layout (eg. when disabling the CSS - something that was still possible at the time), which was beneficial for accessibility.
brightball
The “across all browsers” problem was such a huge pain. Not just for CSS but JS too.
I still remember the campaign for sites to drop support for IE6 in protest.
radicalbyte
Yeah fun times.
I kept our internal reporting site running for 3-4 years, I used CSS for layout.. it required regular maintenance but I had enough time to do it as my main job was as a Database Admin / Data Engineer (I'd have been called "devops engineer" nowadays as I had quite a broad set of responsibilities).
padolsey
It always felt like a fun challenge. For me, it was a crucial part of my love of the web (and eventually, programming): the hackability and the way that there was no canonical correct way to solve a given problem. I miss those days.
elevaet
I remember a time when using <div> tags was considered a sign of "expensive" to some.
flibertyjibbet
[dead]
90s_dev
Not to mention that early on, CSS was very lacking compared to today. We didn't even have `border-radius` until something like 2011! Consider that this relatively simple site design[1] takes about 420 lines of modern CSS[2]. And that's even using nesting, and liberal use of :has, which is a game changer. I remember having to restructure both my CSS and my HTML to achieve appearances which were otherwise impossible to create in the intuitive way, all because of inherent limitations to CSS at the time.
[1] https://90s.dev/
katzgrau
Re border radius… The coveted rounded corner, the mark of a really slick design before that property made it easy :D
I think media queries/responsive is what did in the last bastion of CSS resistors.
darau1
Modern CSS makes me long for Hi5 to make a comback. My profile would be killer.
kreetx
I'm fuzzy on the timeline, but there was a time where the emerging CSS wasn't up to the task of creating more complex layouts (no flexbox, not to speak of the grid). CSS Zen Garden was just there to show what could be done by that point.
JimDabell
Things have certainly gotten easier, but even back then CSS had things like pseudo-elements and display: table-cell. The main problem was Internet Explorer 6 holding everybody back so floats were the main way of laying things out, and those go back to CSS 1 (1996).
Macha
floats and clearfix were plenty powerful even before flexbox, despite not being intended for the purpose.
But then, neither were tables.
throw310822
> layouts were implemented by abusing table elements to create a grid.
Never understood what was actually wrong with it, apart from the whole "semantic html" yadda yadda that is meaningful for a small subset of applications.
jdance
Yeah me neither, I think the CSS being cool and hard to use was the real reason. People like being ”elite”, and tables were just dead simple.
I am surprised people here still hold on to that era of CSS. There are even people in the comments being proud of clearfix
But I should probably be thankful for CSS for getting me out of webdev early :)
Sharlin
On the contrary, semantics are very important from accessibility point of view.
suspended_state
>> layouts were implemented by abusing table elements to create a grid.
> Never understood what was actually wrong with it
Separation of concerns?
immibis
Creating a grid is exactly the purpose of a table, not an abuse.
padolsey
Semantically speaking, tables are supposed to contain tabular data, not to be used solely for their layout capabilities. That's why it's called an abuse.
Sharlin
> Tables have existed as part of web standards since the HTML 3.2 standard (January 1997). The standard referenced an earlier RFC and was intended to be compliant with the table tags Netscape had already added to their browser, but this was their official addition to the HTML standard.
> The standard pointed out that tables could be used for tabular data or layout purposes, but cautioned that using them for layout would impact accessibility.
> In HTML 4 (April 1998), this warning was strengthened to "Tables should not be used purely as a means to layout document content", and we were pointed to the addition of CSS1 to help accommodate this. It was noted, however, that using deprecated features was expected to continue for a little while [heh] in order to support older browsers (browser listed above).
https://www.tiernok.com/posts/history-of-html-table-layouts....
JimDabell
An HTML table describes data that is related across multiple axes. A grid is a typical presentation for that data. That does not mean that creating a grid is the purpose of a table, and it doesn’t mean that any instance of a grid should be a table.
null
unconed
With all due respect to Dave, no. Please stop rewriting history without the relevant details.
CSS Zen Garden is a project that demonstrated that "progressive enhancement" and "semantic HTML" were nonsense. The only reason something like CSS Zen Garden worked at all is because all the markup is fixed, all the content is static, and the designs are not really responsive.
There is no CMS with a theming system that offers the flexibility that CSS Zen Garden claims one can have with a single .css, independent of the HTML. And this is because web developers were huffing the HTML/CSS gospel too much, fussing over not having extra divs in their source and what not, and celebrating "semantic HTML" without ever running their website through a screen reader.
The reason people stopped using table layout when they were doing CSS is because CSS1 did not support the _most common way of doing layout at the time_, and IE6 held the web hostage for a decade. This is a remarkable thing because it means everyone hopped on this bandwagon despite it being very obviously ill-informed and not ready for production. The CSS Zen Garden era designs can be expected to be full of float/clear tricks, requiring careful layout dependency between elements so everything gets pushed down just far enough. And it looks exactly like the table-based layouts they were replacing, except they will scale improperly or not at all.
The "status quo" attitude has also not vanished, as witnessed by CSS variables, custom properties and all the other epicycles that keep getting added on to CSS instead of actually just scrapping the parts that are dumb. None of these CSS experts have the vision or depth of experience to really know what it takes to implement what they spec, or what is even still relevant today and what isn't.
I actually implemented my own web layout system for Use.GPU from scratch, with flexbox and blackjack and hookers, and it's remarkable how much of HTML/CSS you don't need, and also, how many parts of it are still laughably inadequate (like text-ellipsis).
Dave did not win the argument. The people who celebrated CSS Zen Garden were cargo culters who confused a pretty design for a structurally sound layout, and who honestly just wanted something they could feel good about while dealing with pre-Firebug / pre-Dev Tools CSS development.
There is a really easy way to test this too, and I would challenge Dave to do it: translate all the content to another language. See how many of those beautiful CSS-only designs fall apart.
JimDabell
This sounds less like you want to correct something I have said that was inaccurate and more like you have a fundamental disagreement with the design of CSS.
DaiPlusPlus
If that's how your feel about CSS, what do you think about XSLT?
timeon
You could easily make float/clear layout for dynamic content.
Griffinsauce
> [IE] held the web hostage for a decade.
I wonder whether we'll ever get to reach this point with Safari. Especially with regards to PWAs and the insane state of "native" apps.
null
tzury
This site is old, and I mean it in a good way.
This site was a "culture" shock for me, back in 200x and made me walk away from Microsoft ASP.NET and start building apps on linux, realizing all those "server controls" with inline style parameters were basically the complete wrong way, the "anti internet way".
It was Alex Russell (creator of Dojo JS) who showed that side in one of the conferences, and I was shocked how much information I was missing while getting my technical news through Microsoft channels.
For many years, my toolkit was simply Web.py, HTML, JS and CSS.
We then got jQuery, and Backbone, and Underscore, till the React and then TS made new "Full stack" dumber again.
wordofx
> This site was a "culture" shock for me, back in 200x and made me walk away from Microsoft ASP.NET and start building apps on linux
What stopped you from building such apps on Asp.net? It didn’t prevent you from building anything like that. You could stop creates style sheets and separate JS files.
> realizing all those "server controls" with inline style parameters were basically the complete wrong way, the "anti internet way".
Ironically what’s old is new again because we have literally gone full circle even down to nextjs? Recreating view state… and tailwind with inline styling and shadcn with react components.
tzury
Indeed. The famous asp.net "__VIEWSTATE" is now back to life...
undebuggable
> made me walk away from Microsoft ASP.NET and start building apps on linux, realizing all those "server controls" with inline style parameters were basically the complete wrong way, the "anti internet way".
That's still online, although as an outdated relict: https://www.ajaxtoolkit.net/. There was no enterprise software without drag panel!
For a moment semantic markup and CSS had taken the lead but nowadays I don't even care enough to check what the trends are. Stopped caring around the moment of "HTML inside JavaScript" (JSX).
radicalbyte
I started writing ASP & PHP, the whole ASP.Net thing was about helping Visual Studio developers make crappy web apps, it wasn't fit for purpose for the web writ large.
You didn't need to switch to Linux either; I built everything under Windows (IT didn't allow Linux desktops) and deployed it to both Windows and Linux servers.
tucnak
Svelte now exists; it's a bit of a "clever" fullstack
pinoy420
[dead]
rendaw
I feel like the main point of css zen garden was how, by maximizing your use of semantic HTML, you could separate the presentation from the content and operate on them completely independently.
While you can still do this to the extent zen garden does, it's really operating within the limits of css (i.e. css can do this, therefore I can create this type of design, not I want this type of design, therefore I need to write this css).
There are lots of style choices that require modifying the DOM directly to effect, and can't be done purely with CSS. I've seen discussions on W3C where it was like "Well if you add another div around this you can achieve this effect, so why do we need a new CSS property?". Stuff like inserting or swapping an image is simple, but swapping a styleable SVG is impossible because the SVG nodes need to be directly embedded in the html.
So you're forced to mix presentation and content structuring decisions at the HTML and Javascript levels and even some simple design changes require modifications throughout the stack.
90s_dev
The CSS community's promise was always that structure and presentation can be separated.
After my 30 years of writing GUIs, I'm now convinced that this is the wrong place to draw a dividing line.
Instead, we should be isolating intent. This is what Composites do in my project. I'm so excited to announce it next week!
kalleboo
Enter stage: XSLT
zelphirkalt
On the other hand CSS is very capable these days and many designs, that actually are not flying air castles and take the medium into account, can be implemented flawlessly using only CSS and HTML.
leo-notte
Agreed. A lot of modern web design problems come from trying to force a medium to do something it was never meant for. If you work with the grain of HTML and CSS instead of against it, you can still build really flexible and beautiful layouts without needing to hack the DOM or pile on JS. zen garden was a reminder of that and it still holds up.
meekaaku
As someone who learned CSS from Zen Garden and the likes of Eric Meyer, modern css tools like Tailwind looks like an anti pattern
throwaway150
Absolutely! There are so many problems with Tailwind.
The HTML is littered with styling information. Reading HTML should be about content and meaning, not knowing that "pl-16 pr-8 bg-olive-500 text-gray-700" means "this is probably a card header". But... you might argue that people do not read HTML anymore. Yes, people don't read HTML anymore. Who would when the devs using this framework turn the HTML into a horrible mess! If you litter your HTML with so many framework classes, there is more noise than content in HTML. Is it a surprise that reading HTML has fallen out of fashion? And since nobody reads HTML anymore, devs are totally unhinged with cluttering it with more and more classes and styles. It's a self perpetuating cycle.
Webdevs do style duplication rampantly. Instead of something like ".button", you'd find stuff like "text-white rounded bg-gray-aaa" littered throughout hundreds of places. I'm not sure if this is a Tailwind problem or dev problem but the problem definitely is there. A large project would soon reach a situation where if you want to make a style change across all similar UI elements it's a whack-a-mole game to find out which inline styles in which elements you need to look at.
brailsafe
I have a fairly strong grasp on CSS, at one point having what I felt was as close to as knowledgeable as I'd care to be about it, but one thing always stuck out as a neverending battle; style organization. I think Tailwind does have all those problems to some extent, but CSS alone didn't find cultural consensus around how best to implement it, always leaning on whichever flavour of the month conceptual framework that was often just one more system to try to manage. There's some virtue in writing the stuff you do cleanly, but sometimes it's just not as valuable to someone who's primarily doing what could be described as complex software development. Sometimes the marginal benefit to a clean implementation and a slightly messy redundant one of the same interactive caliber just isn't that important relatively, especially when the negative qualities are somewhat mitigated by component re-use and scoping.
chuckadams
I think it's the complex specificity rules that prompted things like TW to come about. Sure it's useful and powerful but it's utterly baffling to reason about, especially when everyone's conventions work at a different level of specificity. Trying to tame specificity gave us cumbersome structures like BEM, and TW came about as an act of rebellion against such things.
Conversations about CSS complexity always remind of this quip: "Two CSS selectors walk into a bar. A bar stool on the other side of town falls over."
chuckadams
It's a culture problem with Tailwind devs: for a long time there was a crusade against `@apply` in favor of inlining every class. I think the reason was solely because TW's tree-shaking wasn't very capable then and did even worse with @apply, but the air was thick with specious "philosophical" justifications flying around for inlining all the things. The most typical was "it should always be done through a component toolkit", which of course just buries the problem in javascript -- not to mention doing it dynamically is incompatible with tree shaking, so you end up having to predeclare everything you use...
Nowadays the anti-@apply contingent seems to have gone quiet, so it is possible to not only use TW and similar toolkits sanely (which has always been the case) but to even see people publicly advocating for sanity.
ookblah
yeah, and then one day you want .button, but with a variation. GREAT. but oh no, now there's this other button that has a little bit of a change but not enough to create a separate class. maybe we'll just inline it... but no, i need a mobile selector here or i have some complex hover style. i know, let's create a basic utility class to help me out here. hmm, starting to look suspiciously like tailwind...
now multiply this problem by more people working on an app, with different isolated components that they never even dreamed of during css zen garden's time and this is how something arose. we've tried creating centralized css sheets and it just doesn't work at scale.
so yeah, a necessary evil, but i wouldn't call it an anti-pattern. it grew out of real needs. we had bootstrap and all these css frameworks attempting to make "order" about of something that honestly after decades of working with i don't think can be ever be fully "clean". people just gotta move past it.
amjoshuamichael
I think CSS tools like that appeal to people who learned web development in a kind of ad-hoc way. When I first started, I just wanted to make designs I had in my head. I kind of went from "header, text, and image on the page" to, "how do I center this?", "how do I change this color?", "how do I space these elements out?" It wasn't long before I had developed a toolkit of CSS ideas, but once you do that, you lose out on a lot of the finer details that make CSS work well. I knew how to work around weird issues using position: absolute and transform, but I wasn't familiar with block formatting contexts, or the intricacies of the box model. When all of your CSS knowledge is just band-aids placed on your other shoddy CSS knowledge, you're working on fumes. At that point, you could imagine the appeal of grabbing a prebuilt toolkit of composable styles that takes away your access a lot of the available CSS footguns.
What changed things for me was reading an short online book-style series about learning HTML/CSS from the ground up. It introduced everything from first principles, and had an approach where they explained why things were the way they were. They didn't just give you their "top 10 ways to center a div" and ask you to leave. I read the whole thing in an afternoon and it changed the way I think about web development. For the life of me, I can't remember what the book was called. If anyone's read something similar I'd love a reference, it was a while ago now and I'd still like to reference it. I specifically remember them saying "display: block is like a word document, and display: flex is like how you'd expect things to work," which illuminated a lot for me, not just about the display property, but generally about the way HTML & CSS were designed.
theyknowitsxmas
I think it works well and is a good standard for companies with hundreds of people. Want to style everything one-off in a landing page go ahead.
pier25
A bit of light in the dark ages of Tailwind and CSS-in-JS.
It's difficult to realize how significant CSS Zen Garden was 20 years ago or so.
paavohtl
CSS-in-JS (like how Styled Components and Emotion do it) is primarily a solution to code organization. It doesn't fundamentally change how CSS works.
pier25
But it's a performance killer
https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-...
Edit:
See also this thread on Bluesky
https://bsky.app/profile/infrequently.org/post/3lnehf53bpcl7
spiderfarmer
It made me fall in love CSS for sure. But it didn’t prevent me from understanding the appeal of Tailwind for large scale projects.
nuw
Please enlighten me of the benefits of using tailwind in large projects as opposed to using inline styles.
9dev
Not having to name a myriad of things! Sure, things like BEM can help you at least avoid naming conflicts, but you still have to decide a few thousand times what something is called semantically correct, in a way that you and your French colleagues and the intern of next year are going to understand it.
When I got productive with Tailscale, I finally realised how many brain cycles I wasted on this. I’m, like, a programmer; of course I’ll obsess over picking the perfect name. Of course I will not be happy with the names my junior picked, and of course I will constantly be unhappy with some of them. This game of self-inflicted bike shedding is just a trap for people that like logic and order, and it’s… wholly irrelevant.
With tailwind, you just declare how something is supposed to look and feel like, at the place where it is, in the context of your configurable design system. No names, no bike shedding. Okay, that’s not a hundred percent true; you can name group selectors, because as opposed to plain inline styles, Tailwind can target children, siblings, pseudo elements—there are no restrictions.
It’s a truly elegant solution for authoring web pages.
halflife
Configuration. Inline styles are direct style Implementations in your html, tailwind is an abstraction that lets your configure and refactor easily. I can say from experience, being in charge of developing a large product that was bought and merged into a larger corporation, using tailwind from the start allowed us a refactor our app’s design within 1 day instead of it being several weeks worth of work.
And as a bonus it provides best practices in css scaffolding of a product design (typography, grid, colors)
ookblah
mobile selectors, "group" selectors, hover styles... the list goes on and on. like all things, it depends on how your workflow. if you have a super defined hierarchy and naming scheme you can reference then sure, centralize all your CSS. if you have many components and multiple people working on them sometimes it's better to separate everything out and enforce with a guide.
i can't tell you how frustrating it is to open a component and have no idea what you're looking at because you worked on the thing months ago, or you change one thing in your centralized CSS and have no idea what the side effect are. with tailwind i can see exactly the styles i'm looking for.
FOR ME, works better to have a core style file and then move everything to something like tailwind per component for maintenance.
tired of seeing the same simplistic arguments against utility frameworks. if you can't see the merits of it then you obviously aren't working on projects that need that, but don't criticize it blindly. it's not for lack of CSS knowledge.
spiderfarmer
Tailwind makes things like dark mode and group hover/focus states dead simple with modifiers (dark:, group-hover:), keeping all your logic in your HTML. With inline CSS, you’d need messy JS, extra classes, or bloated style tags to handle the same.
It also enforces a design system (spacing, colors, fonts), while inline CSS often leads to small, inconsistent differences everywhere.
It’s a great solution to a problem a lot of people were having. That’s why it’s so popular.
parrit
Even on one element you can combine tailwind classes. With styles you need to write out the final result.
Then you can also use @apply if you wish but leave that out of the argument as it is considered unidiomatic.
Of course if using React you can also use styles directly and then create your own utilities to determine how they compose. Which might give you much of the Tailwind edge without needing the compile step.
memonkey
They published a book that I purchased when I was first learning CSS. Truly a different era.
thm
I had two designs there and to this day, I get emails from people seeking permission to reuse the CSS.
kreetx
This site had huge effect on me back in the day!
For those who don't know: for the same html content you could submit a design in CSS and images. For example these impressed me the most:
- https://csszengarden.com/202/
- https://csszengarden.com/189/
- https://csszengarden.com/177/
- https://csszengarden.com/136/
- https://csszengarden.com/206/
There was also one which had a position: fixed knife "cutting the page from the middle" when you scrolled, but it doesn't seem to be on the list anymore. Edit: and another one I remember was like so that the top of the page is sea level and you'd scroll to the bottom of the sea, where there was either an octopus, a submarine or a diver, can't remember.
voidfunc
Blast from the past... I loved the CSS Zen Garden but it's goals and philosophy were oriented to a world where the primary purpose of a website was to serve documents. Our rich media world sort of left this vision of the web in the dust sometime in the mid 2000s.
bigbuppo
I wouldn't say it's rich media, but the conversion of the web to be 100% marketing-driven. It's ads all the way down.
nathell
That’s a serious downgrade.
est
Is "modern media" really rich? I think information density and signal-noise actually degrades
kome
"a world where the primary purpose of a website was to serve documents"
we are still living in this world. and i don't mean it snarkily. beside some maps application, most of the web is still about reading stuff, and it doesn't need so much cruft. it's getting more complex just because developers prefer complexity over simplicity.
switch007
De facto it's a web app, not a document, world. Have you tried browsing without JavaScript recently? It's even worse in this AI era when content sites want proof of work, only available via JavaScript.
alxmdev
Glad to see the Garden is back! This and Spoono were some of my favorite websites back when CSS-driven web design was bleeding edge and people were just starting to use lots of nested divs instead of lots of nested tables. The book was nice too.
throwaway150
So happy to see CSS Zen Garden on HN today! Those were the days!
But I've also got to rant now.
What I find most troubling about Tailwind and CSS "frameworks" like it (and modern software development in general) is the growing pride in not understanding the underlying systems.
Tailwind offers a quick, surface-level solution: you can slap some utility classes onto a page and get something that looks "good enough" without ever learning how CSS actually works. Nevermind that the HTML is now a mess where you've got more CSS classes than content!
The attitude is, "Who cares how it works? I got my pretty page. That's a win!"
But this isn't just a Tailwind problem. It's part of a larger trend in the industry: celebrating ignorance, rushing for results without building real understanding.
When did not knowing become something to be proud of? Isn't it sad that depth and mastery are now treated as optional, even undesirable?
/rant
budgi4
Software development is a layering of abstractions over time. How's your assembly?
vacuity
How's your Electron app's performance?
It's very concerning when software developers neglect that their tools (abstractions) have tradeoffs.
"If civil engineers built bridges the way software engineers build applications, the bridges would all fall down in a month".
And similar sentiments. Granted, most things aren't mission-critical, but then just because my house won't collapse doesn't mean I want to waste money on poor insulation and broken appliances.
panstromek
I get the idea, but don't think that's the case for Tailwind. Tailwind classes map directly to CSS properties, you can't really do much with it if you don't understand CSS
throwaway150
Are you sure? Could it be confirmation bias because you do understand the CSS?
From what I've seen across multiple teams, it's very common for developers to just slap Tailwind onto their project, copy-paste classes they found online and call it "done." Maintainability and reusability are treated as someone else's problem.
bcye
Copy-pasting code and calling it done isn't limited to Tailwind though.
antirez
The idea of CSS Zen Garden, that was: to show that you can produce server side simple and semantic HTML, and CSS will be enough to do the rest for the presentation of the content, was an incredible innovation of 200x that was totally forgotten, and that now, younger generation of programmers that grown up with big web frameworks no longer "get". They see CSS as something complex and impossible to handle, exactly because of what modern HTML is (because of such frameworks), without realizing that this is indeed the same problem: that modern web sucks, not that CSS sucks.
pavlov
What changed was that “web 2.0” happened. Web design’s focus changed from documents to applications.
CSS Zen Garden was about styling “web 1.0” HTML documents.
But dynamic UIs have completely different styling needs. People started building JavaScript applications, and they started needing UI layouts similar to those provided by desktop UI frameworks. And CSS was never designed for that. Concepts like “float” were entirely derived from the word processor universe. CSS had to add several complex new layout engines over the following decades.
pantulis
There was a book by Dave Shea and Molly Holzschlag called "The zen of CSS design" that explained some of the tricks of the most amazing themes. On my last cleaning I let go of a lot of now obsolete books but that book remains, it's so beautiful!
There’s an aspect of this that is not readily apparent unless you were a web developer around the time this was created.
Before CSS, layouts were implemented by abusing table elements to create a grid. Then images were sliced up into sections, and each section was placed into the table. This has generally been remembered in the present day, however what seems to have been forgotten was the pushback against CSS.
There was a large number of web developers who were happy with the status quo and refused to learn CSS. One of the most persistent myths was that you couldn’t make anything look nice with CSS. Specifically, CSS was accused of only being able to create “boring, boxy” designs.
It wasn’t true at all. Even back in the early days of CSS, you could create great layouts. It was especially absurd because the approach favoured by the people saying this was literally abusing tables to create grids.
So along comes Dave Shea and points out that this is ridiculous, that CSS is capable of great designs, and puts the CSS Zen Garden up. A whole bunch of people contribute good-looking designs and make it impossible for people to claim that “CSS can only produce boring, boxy designs”. I think it’s amusing that he won the argument so conclusively that people forget it was even an argument in the first place.