Documents, apps, Tailwind, and The Web
Call me old fashioned, but the web is not an app development platform, it is a document display platform.
–Me on Twitter in 2010
The web is, fundamentally, for documents. HTML gives those documents structure. Anything new you might want to do for layout or interactivity is added on top of that structure. Tailwind, on the other hand, mimics apps, not documents. That makes it appealing for app developers and out of place on the web.
If you think in a document-oriented way when authoring HTML, you’re first going to think about the page you’re working on as a document. What are the headings? What are the lists? What order should they go in? What other semantics do we need to consider? This approach results in a document structure — like, for example, a scientific paper. Only once the markup is structured do you start laying it out and styling it[1].
Compare that with something like Flutter, Google’s modern app UI framework. It, along with Apple’s similar SwiftUI, are how the two companies who own the biggest app platforms out there think about structuring apps:
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(color: Colors.white),
child: const Center(
child: Text(
'Hello World',
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 32,
color: Colors.black87,
),
),
),
);
}
Everything is a widget, and every widget serves some purpose for layout or style. Yes, there is a hierarchical structure that is arguably analogous to the DOM, but it is not, and never was, meant to describe a document. Much of the structure is directly intended to describe the layout; the widget tree structure and the layout on screen are completely inseparable.
And the reality is that many apps aren’t documents; they’re (gasp) apps. I have no idea how accessibility works in Flutter or SwiftUI, but I appreciate that this approach does make a lot of sense for declarative app UI. This, I think is the appeal of Tailwind: it lets someone author for the web as if they’re writing an app: with semantically meaningless widgets whose purpose is just to provide layout and styling (i.e., <div>s with utility classes).
For those of us who are web-minded people, though, this feels weird and uncomfortable. It absolutely cuts against the grain of the web, and throws away so much of the progressive enhancement and accessibility that comes with the web platform for free. To us — and everyone who benefits from that progressive enhancement and accessibility — this is not a good thing.
I think these two philosophies of the web — web as app development platform and web as document distribution platform — are exactly why Tailwind gets so much love and so much hate from different factions.
I’ll leave with a provocation for those of us who are squarely in the Document camp: how do layout-only utility Web Components (e.g., Nord’s Stack) fit into this picture? Are they at home on the web? Are they like Flutter and SwiftUI’s layout-only widgets? And can they be both?
Of course this isn’t strictly how the real world always works, but it’s an ideal. ↩︎