Beyond Tailwind: Structuring Modern Vanilla CSS
After eight years of using Tailwind, the author is migrating to a vanilla CSS system that incorporates Tailwind's best organizational principles. By leveraging modern features like CSS Grid and native nesting, they have created a component-based architecture that is more flexible and lightweight. This transition reduces reliance on heavy build systems while allowing for more semantic HTML and sophisticated layout techniques.
Key Points
- Tailwind served as a valuable educational tool that taught the author how to use resets, color palettes, and font scales.
- Modern CSS now natively supports features like nesting and imports, reducing the need for complex build tools or preprocessors.
- Organizing CSS into discrete 'components' with unique classes and separate files provides maintainability without framework overhead.
- Advanced CSS Grid techniques allow for responsive designs that require fewer media queries than the standard Tailwind approach.
- The move to vanilla CSS allows for smaller production bundles and the freedom to use 'weird' or advanced CSS features that utility frameworks limit.
Sentiment
The community is deeply divided but leans slightly toward agreement with the article. Many experienced developers acknowledge that modern CSS has evolved enough to make vanilla CSS viable again, and there's broad agreement that understanding CSS fundamentals matters. However, a substantial and vocal contingent of Tailwind users pushes back strongly, arguing the framework's productivity benefits outweigh philosophical concerns about separation of concerns. The debate is more nuanced than a simple for-or-against — many commenters appreciate both perspectives and see the choice as context-dependent.
In Agreement
- Modern CSS features like native nesting, variables, @layer, @scope, and CSS Grid now make it possible to write well-structured vanilla CSS without frameworks
- Tailwind's utility-first approach inverts the proper HTML-first workflow and ergonomically encourages div soup, even if it doesn't force it
- Separation of concerns between HTML and CSS remains valuable for maintainability, cacheability, and clean architecture
- Semantic HTML is essential for accessibility, and Tailwind's examples and design loop don't encourage semantic markup
- ITCSS and other organizational patterns provide structured approaches to vanilla CSS that tame the cascade without utility classes
- The global namespace problem in CSS is now solvable with CSS Modules, @scope, native nesting, and component-scoped styles
- CSS should be learned properly rather than abstracted away, as understanding the cascade and specificity makes developers more effective
Opposed
- Tailwind provides unmatched developer productivity — styles co-located with markup reduce cognitive load and eliminate context-switching between files
- Nothing about Tailwind forces inaccessible markup; experienced developers can and do write semantic HTML with Tailwind
- Tailwind provides consistency across projects and teams — any developer familiar with Tailwind can immediately contribute to any Tailwind codebase
- The cascade is fundamentally a footgun in large codebases, and Tailwind's component-scoped approach eliminates specificity wars entirely
- DRY is overrated — premature CSS abstractions often create worse maintainability problems than utility class repetition
- Tailwind's tree-shaking produces optimally small CSS bundles with zero unused styles shipped to production
- LLMs write Tailwind exceptionally well, making it the superior choice in the AI-assisted development era
- The distinction between documents and applications matters — Tailwind excels for UI-heavy applications where component-based architecture is the norm