Why I Still Write Vanilla CSS
Posted on March 2025 - 4 min read
Vanilla CSS remains a strong option when teams need direct control, minimal dependencies, and clear ownership of styling decisions. This piece explains when that tradeoff is worth taking.
The Framework Hype Cycle
Every few years, a new CSS framework emerges promising to solve all our styling problems. From Bootstrap to Tailwind, from Emotion to Styled Components, each brings its own philosophy and tradeoffs. While these tools have their place, I’ve found myself returning to plain CSS more often than not.
The pattern is familiar: a framework gains popularity, developers adopt it enthusiastically, and eventually some of us realize the complexity cost outweighs the benefits for our specific use cases.
When Vanilla CSS Shines
1. Small to Medium-Sized Projects
For projects with a limited number of components and pages, setting up a CSS framework often adds more overhead than it saves. The time spent configuring build tools, learning framework-specific syntax, and fighting against framework defaults could be spent writing actual styles.
/* Simple, readable vanilla CSS */
.button {
padding: 0.75rem 1.5rem;
background: #3b82f6;
color: white;
border-radius: 0.5rem;
font-weight: 600;
transition: background 0.2s ease;
}
.button:hover {
background: #2563eb;
}
Compare this to the equivalent in many frameworks where you need to understand their specific class naming conventions, utility combinations, or JavaScript-based styling APIs.
2. Performance-Critical Applications
Every dependency you add to your project comes with a cost. CSS frameworks bundle thousands of lines of code, most of which you’ll never use. Even with tree-shaking and purging, there’s always some overhead.
Vanilla CSS gives you complete control over what gets shipped to the browser. You write exactly what you need, nothing more. For performance-sensitive applications, this matters.
3. Team Ownership and Knowledge Transfer
When you use a framework, you introduce a dependency on external documentation and community knowledge. Team members need to learn framework-specific patterns that don’t transfer to other projects.
With vanilla CSS, the skills are universal. Any developer who knows CSS can contribute effectively. This becomes especially important for:
- Teams with high turnover
- Open source projects with diverse contributors
- Organizations that work on multiple projects with different tech stacks
4. Long-Term Maintenance
CSS frameworks evolve quickly. What’s current today may be deprecated tomorrow. Your Tailwind v2 code might need significant updates for v3. Your styled-components setup might break with a React version upgrade.
Vanilla CSS, by contrast, is incredibly stable. CSS features added years ago continue to work today. The learning curve you invest in pays dividends across your entire career.
Modern CSS is Powerful
One reason vanilla CSS gets overlooked is that many developers aren’t aware of how much the language has evolved. Modern CSS includes features that make many framework conveniences unnecessary:
CSS Custom Properties
:root {
--primary-color: #3b82f6;
--spacing-unit: 0.25rem;
--border-radius: 0.5rem;
}
.card {
padding: calc(var(--spacing-unit) * 4);
background: var(--primary-color);
border-radius: var(--border-radius);
}
Custom properties give you variables and theming capabilities that rival what frameworks offer.
CSS Grid and Flexbox
.grid-layout {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
Modern layout systems make complex layouts straightforward without framework utilities.
Container Queries
.card {
container-type: inline-size;
}
@container (min-width: 400px) {
.card-title {
font-size: 1.5rem;
}
}
Container queries let components respond to their own context, not just the viewport—a feature many frameworks still struggle to support well.
The Framework Sweet Spot
This isn’t an argument that frameworks are never useful. They absolutely have their place:
- Rapid prototyping when you need something working quickly
- Design systems where consistency across many components is critical
- Large teams that benefit from constrained styling choices
- Legacy codebases where adopting a framework can standardize inconsistent styles
The key is recognizing when the benefits outweigh the costs.
My Decision Framework
When starting a new project, I ask myself these questions:
- How complex is the UI? Simple interfaces often don’t need framework overhead.
- What’s the team size and turnover? Smaller, stable teams benefit from vanilla CSS’s simplicity.
- Are performance requirements strict? Every byte matters for some applications.
- How long will this project live? Long-term projects benefit from stable, standard CSS.
- Do we have existing design tokens? If yes, vanilla CSS can leverage them directly.
If the answers lean toward simplicity, performance, and longevity, I choose vanilla CSS.
Practical Tips for Vanilla CSS
If you’re considering returning to plain CSS, here are some practices that help:
- Use CSS custom properties for consistency and theming
- Organize with CSS modules or scoped styles to avoid naming conflicts
- Leverage modern features like container queries and cascade layers
- Build small utility classes for repetitive patterns (but don’t recreate Tailwind)
- Use a linter like Stylelint to maintain code quality
/* Example: organized, maintainable vanilla CSS */
:root {
/* Colors */
--color-primary: #3b82f6;
--color-primary-dark: #2563eb;
/* Spacing */
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
/* Typography */
--font-sans: system-ui, -apple-system, sans-serif;
}
/* Component styles */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--space-sm) var(--space-lg);
font-family: var(--font-sans);
font-weight: 600;
border-radius: 0.5rem;
border: none;
cursor: pointer;
transition: all 0.2s ease;
}
.btn--primary {
background: var(--color-primary);
color: white;
}
.btn--primary:hover {
background: var(--color-primary-dark);
}
Conclusion
The best tool depends on the problem. CSS frameworks solve real problems for many teams. But vanilla CSS remains a powerful, capable option that deserves serious consideration—especially for projects where simplicity, performance, and long-term maintainability matter.
Don’t let framework hype obscure the fact that CSS itself is a mature, capable language. Sometimes the best solution is the simplest one.
Write the CSS you need, understand what you write, and ship code that you and your team can maintain for years to come.