Most Bootstrap utilities have a direct Tailwind twin (d-flex to flex, text-center stays text-center), but spacing numbers and breakpoints differ, and components like modals and dropdowns need their JavaScript replaced. Migrate one page or component at a time.
Class mapping for the common cases
d-flex justify-content-between align-items-centerbecomesflex justify-between items-center.d-none d-md-blockbecomeshidden md:block.row+col-md-6becomesgrid md:grid-cols-2 gap-6(orflex flex-wrapwithmd:w-1/2).fw-boldbecomesfont-bold,text-mutedbecomes something liketext-gray-500.roundedstaysrounded,shadow-smbecomesshadow-smorshadow-xsdepending on how strong you want it.w-100becomesw-full,mx-autostaysmx-auto.
Spacing numbers do not line up
Bootstrap 5 spacing utilities use a 0 to 5 scale where 3 is 1rem. Tailwind uses 0.25rem steps, so the same number means something different:
mt-1(0.25rem) staysmt-1.mt-2(0.5rem) staysmt-2.mt-3(1rem) becomesmt-4.mt-4(1.5rem) becomesmt-6.mt-5(3rem) becomesmt-12.
A blind find-and-replace of mt-3 will silently shrink your spacing. Map by value, not by name.
Breakpoints are different too
Bootstrap 5 breakpoints are 576, 768, 992, 1200 and 1400px. Tailwind's defaults are 640, 768, 1024, 1280 and 1536px. Only md matches. If layouts must switch at the same widths, override the breakpoints in your theme:
@import "tailwindcss";
@theme {
--breakpoint-sm: 36rem;
--breakpoint-lg: 62rem;
--breakpoint-xl: 75rem;
--breakpoint-2xl: 87.5rem;
}Or use a one-off value like min-[992px]:flex where only a few places need it.
Components and JavaScript
A Bootstrap button is a single class. In Tailwind you spell it out, then wrap it in a component so you write it once:
<!-- Bootstrap -->
<button class="btn btn-primary">Save</button>
<!-- Tailwind -->
<button class="rounded-md bg-blue-600 px-3 py-1.5 font-medium text-white hover:bg-blue-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600">Save</button>Modals, dropdowns, collapses and tooltips depend on Bootstrap's JavaScript, which reads data-bs-* attributes. Tailwind has no JavaScript. Replace them with native elements (<dialog>, <details>), a small library like Alpine.js, or headless components from your framework. Keep Bootstrap loaded until the last of those is gone.
Convert rendered Bootstrap with PickCode
- Run the Bootstrap page. Open your app locally with Bootstrap still loaded.
- Pick a component. Press Alt Shift C and select a card, navbar or form.
- Copy as Tailwind. PickCode reads the styles Bootstrap actually applied and maps them to the default Tailwind scale, so mt-3 comes out by value, not by name.
- Swap it in. Paste the Tailwind version in place of the Bootstrap markup and remove the old classes.
- Rewire the JavaScript. Replace data-bs toggles with your own code. Copying never brings behavior.
Questions
Can I run Bootstrap and Tailwind together during the migration?
Yes, but expect conflicts: both define classes like container, rounded and shadow-sm. A Tailwind prefix avoids clashes until Bootstrap is gone.
Is there a direct grid equivalent to Bootstrap columns?
CSS grid in Tailwind is usually simpler: grid grid-cols-12 with col-span-6 mirrors a 12-column layout, and md:grid-cols-2 covers most cases.
What replaces Bootstrap form styles?
The official @tailwindcss/forms plugin resets form controls so utilities work on them. Add your own classes for the look.
Should I convert everything at once?
No. Convert page by page or component by component, and test each at phone and desktop widths before moving on.