Something is happening in front-end development that nobody wants to talk about. A generation of developers are entering the workforce who can build beautiful interfaces but cannot explain how a flexbox actually works. They can ship features faster than ever, but the moment something breaks in a way Tailwind does not account for, they are completely stuck.
I am not here to bash Tailwind. I use it. It is a genuinely good tool that solves real problems. But we have collectively confused “faster” with “better” and are now paying the price in technical debt and mass-produced helplessness.
The Tailwind Bargain
Tailwind’s pitch is compelling: stop context-switching between HTML and CSS files, stop inventing class names, stop fighting specificity wars. Just slap some utility classes on your elements and move on with your life.
And it works. I have shipped projects faster with Tailwind than I ever did writing vanilla CSS. The design system constraints baked into the framework mean fewer decisions, fewer inconsistencies, and fewer “why is this 17 pixels and that one 18 pixels” conversations in code review.
But here is the thing about abstractions: they are wonderful until they are not. Every abstraction hides complexity, and hidden complexity does not disappear. It just waits.
What Gets Lost
I have been interviewing front-end candidates for years. The shift is unmistakable. Five years ago, I could ask someone to centre a div and expect a conversation about different approaches: flexbox versus grid versus the old margin auto trick. We would talk about trade-offs.
Now I get blank stares followed by “I would use Tailwind’s flex and justify-center classes.” Okay, but what do those classes do? What CSS properties are being applied? Why does justify-center work on the main axis and not the cross axis? Silence.
This is not elitism. This is a fundamental gap in understanding that will bite you the moment you:
- Need to debug a layout issue in production where the dev tools show you actual CSS, not utility classes
- Work on a project that does not use Tailwind
- Encounter a browser rendering bug that requires understanding the cascade
- Have to write a print stylesheet
- Need to animate something beyond what Tailwind’s transition utilities offer
- Inherit a legacy codebase written in SCSS or plain CSS
The browser does not speak Tailwind. It speaks CSS. When things go wrong, you need to speak CSS too.
The Debugging Gap
Here is a scenario I have seen play out repeatedly. A developer builds a component using Tailwind. It looks perfect in Chrome on their MacBook. Then QA files a ticket: the layout is broken on Safari, or on mobile, or at a specific viewport width.
The developer opens dev tools and sees a wall of computed styles. They do not know what align-items: stretch means or why it is being applied. They do not understand why their flex child is overflowing its container. They cannot read the box model diagram because they have never had to.
So they do what anyone would do: they start adding more utility classes. overflow-hidden. shrink-0. min-w-0. They are not debugging. They are playing whack-a-mole with symptoms while the actual problem, maybe an implicit width from an image or a missing flex-basis, remains unaddressed.
Eventually something works, but nobody knows why. The fix ships. The technical debt compounds.
Tailwind Is a Power Tool, Not Training Wheels
The developers I know who are genuinely productive with Tailwind are the ones who learned CSS first. They understand what the utility classes compile to. When they write grid grid-cols-3 gap-4, they can visualise the underlying display: grid, grid-template-columns: repeat(3, minmax(0, 1fr)), and gap: 1rem.
They use Tailwind as a shorthand for concepts they already understand, not as a magic incantation that makes layouts happen.
This is the part that the “just use Tailwind” crowd misses. The tool assumes knowledge. The documentation assumes knowledge. The debugging process absolutely requires knowledge. We have built an entire ecosystem on top of CSS fundamentals and then told beginners they can skip the fundamentals.
The Bootcamp Problem
I am not blaming bootcamps entirely, but they are part of the picture. When you have 12 weeks to turn someone into a hireable developer, you optimise for shipping visible output. Tailwind lets students build portfolio projects that look professional without understanding what makes them work.
This is rational from the bootcamp’s perspective. Their job is to get people hired. But it creates a pipeline of developers who can produce but cannot maintain, who can build but cannot debug, who can follow patterns but cannot think in first principles.
The first job often reinforces this. The codebase uses Tailwind, the team uses Tailwind, nobody asks you to write vanilla CSS, so why would you ever learn it? By the time you hit a situation where you genuinely need it, you are three years into your career and the gap feels insurmountable.
What Actual CSS Knowledge Looks Like
If you have been using Tailwind as a crutch, here is a non-exhaustive list of things you should actually understand:
The box model. Padding, border, margin, content box versus border box. Why box-sizing: border-box became the default in every reset stylesheet. What happens when margins collapse and why that is actually useful sometimes.
The cascade. Specificity is not just trivia. When you are debugging why a style is not applying, you need to understand selector weight, source order, and the origin of styles. This is literally what the C in CSS stands for.
Display types. Block, inline, inline-block, flex, grid. What each one means for layout flow, how children behave differently inside each context, what properties become relevant or irrelevant based on display type.
Flexbox, properly. Main axis versus cross axis. The difference between justify-content, align-items, and align-content. How flex-grow, flex-shrink, and flex-basis interact. Why flex: 1 is shorthand and what it expands to.
Grid, properly. Explicit versus implicit grids. fr units and how they differ from percentages. minmax(). Auto-fit versus auto-fill. Grid areas and named lines.
Positioning. Static, relative, absolute, fixed, sticky. What “containing block” means and how it changes based on positioning context. Stacking contexts and z-index.
Responsive design. Not just “add breakpoint classes.” Understanding how media queries work, when to use min-width versus max-width, the relationship between CSS pixels and device pixels.
Inheritance. Which properties inherit and which do not. How to force inheritance or break it.
This is not advanced CSS. This is the foundation that everything else, including Tailwind, is built on.
How to Actually Learn This
If you have gotten this far and are feeling defensive, good. That means you recognise the gap. Here is how to close it.
Build something without Tailwind. I know, heresy. But seriously, take a weekend and build a small project using only vanilla CSS. No frameworks, no preprocessors. You will hate it at first and then you will start to understand things you have been cargo-culting for years.
Read the specs. Not the whole thing, that is insane. But pick a feature you use constantly, like flexbox, and read the actual W3C specification. It is more readable than you think and will give you a mental model that tutorials cannot.
Debug other people’s CSS. Volunteer to fix CSS bugs in legacy codebases at work. Nothing teaches the cascade faster than trying to figure out why someone’s !important is not working.
Learn the dev tools. Chrome’s CSS debugging features are incredibly powerful. Learn to use the computed styles panel, the box model visualisation, the layout overlays for grid and flexbox. These tools show you what is actually happening, not what your utility classes say should happen.
Write CSS by hand occasionally. Even if your team uses Tailwind, write your personal projects in vanilla CSS or a light preprocessor. Keep the muscle memory alive.
Tailwind Is Fine. Ignorance Is Not.
I want to be clear about my position here. Tailwind is a good tool. I will keep using it. The productivity gains are real and the design consistency it enforces is valuable.
But using Tailwind without understanding CSS is like using a calculator without understanding arithmetic. It works right up until it does not, and when it does not, you have no foundation to fall back on.
The developers who will thrive in the next decade are the ones who treat frameworks as tools, not as substitutes for knowledge. They understand the browser, they understand the platform, and they reach for abstractions when those abstractions genuinely serve them, not because they cannot function without them.
Learn CSS. Actually learn it. Your future self, staring at a broken layout at 5pm on a Friday with no idea why flex-shrink is not behaving, will thank you.