Migrating from Bootstrap to Tailwind CSS plus daisyUI

by Sanmay Joshi on Oct 23, 2025

I recently migrated Softorage from Twitter Bootstrap (TWBS) to Tailwind CSS + daisyUI (T+D). It was a pretty big exercise, which not just changed the HTML classes, but also DOM structure and consequently JavaScript code.

TWBS often uses data-content HTML attribute for content, like in case of popover and tooltip, whereas T+D uses a simple div structure for such cases with optional data-tip attribute for tooltips. If you have to manipulate data-content in JS, you often have to use hacks and ways that may not always result in a simple, readable JS code. In my opinion, the T+D combo makes DOM into a simplified, easy to understand structure that is easy to work with in JS. For the majority of part, the JS logic and templating logic for T+D turned out be more readable as well, when compared to TWBS. There were also some performance improvements here and there.

Some things that helped with the transition

Here’s a few things that helped me during migration:

  1. Tailwind CSS Prefix:

    1. During the transition I would often need to have both the TWBS and T+D stylesheets to help replicate the existing TWBS behaviour into T+D. Having prefix made that a bit easier. I used Tailwind CSS prefix to help keep the TWBS and T+D classes separate during the transition. The code did become a lot bigger than needed but that was only during the migration. You simply remove the tw: once the transition is completely over and no traces of TWBS are there in stylesheet or JS code.
    2. If you want to style Tailwind CSS classes in your stylesheet, you will styles them with tw\: prefix, which is something you need to remove post transition as well.
    3. In your stylesheet, if you are applying Tailwind CSS classes’ style to some custom classes with @apply, then you need to mention the Tailwind CSS classes with tw:. You will need to remove this tw: from stylesheet once the transition to T+D is complete as well.
    4. I also used the daisyUI with its prefix (dz-), but that is kind of a personal choice as I like to keep things separate.
  2. I found that LLM (AI) help is usually worse than common Tailwind CSS usage with flex/grid (I generally go with flex). There’s a few examples below of AI recommendations. Though I may have simply not given a good enough prompt to get a high quality output.

    TWBSAIMe
    rowflex flex-wrap -mx-2flex flex-col md:flex-row gap-4
    col-md-8w-full md:w-8/12basis-full md:basis-8/12

    You may also be able to get things working with what AI has recommended, but a lot of hacks may be required along the way.

A few TWBS to T+D conversions

Below is a couple of direct TWBS to T+D conversions that I wrote/learned and kept handy during the migration. All classes are there in the Tailwind CSS documentation or daisyUI documentation as the case may be.

TWBST+DRemarks
position-relativetw:relative
leadtw:font-light tw:text-2xl
font-weight-boldtw:font-bold
smalltw:text-sm
display-4tw:text-6xl tw:font-light
d-nonetw:hidden
shadow-smtw:shadow-sm
text-antinavtw:text-base-contenttext-antinav is a custom class for text color. class text-base-content is from daisyui.
text-mutedtw:text-base-content/50
bg-navtw:bg-base-100bg-nav is a custom class used for background.
bg-mattw:bg-base-300bg-nav is a custom class used for background.
bg-whitetw:bg-white
bg-secondarytw:bg-secondary
bg-primarytw:bg-primary
bg-secondary-lighttw:bg-secondary/15I had created this bg-secondary-light class.
bg-primary-lighttw:bg-primary/15I had created this bg-secondary-light class.
rounded-circletw:rounded-full
btntw:dz-btn
btn-smtw:dz-btn-sm
nowraptw:whitespace-nowrap
text-decoration-nonetw:no-underline
text-resettw:text-current
form-check-labeltw:dz-label
form-check-inputtw:dz-checkbox
tabletw:dz-tablerefer daisyui docs.
h1tw:text-4xl / tw:text-5xldepending on TWBS version.
h2tw:text-3xl
h3tw:text-2xl
h4tw:text-2xl
h5tw:text-xl
h6tw:text-base
desktop-onlytw:hidden tw:sm:inline-blockcustom class.
mobile-onlytw:inline-block tw:sm:hiddencustom class.
containertw:max-w-135 tw:md:max-w-285apply centering classes via flex parent. items-center for flex-row and justify-center for flex-col.
container-fluidtw:w-full tw:px-4
rowtw:flex tw:flex-col tw:md:flex-row tw:gap-4the breakpoint in md:flex-row (here md) depends on the breakpoints of children columns, and should generally match with children columns.
col-md-8tw:basis-full tw:md:basis-8/12the breakpoint in md:basis-8/12 (here md) depends on the breakpoints of parent row, and should generally match with parent row.
coltw:growif you want the element to grow to occupy the remaining space.
col-autotw:basis-autoif you want the element to have at least the width apt for its content. no tw:grow to keep the width fix.
cardtw:dz-card tw:bg-base-100
card-bodytw:dz-card-body
card-titletw:dz-card-title
card-decktw:flex tw:md:flex-row tw:flex-col tw:gap-4
cardtw:dz-card tw:bg-base-100 tw:basis-0 tw:growthe card that is child to card-deck.
card-columnstw:sm:columns-3example of 3 columns for sm and above.
cardtw:break-inside-avoid-columnchild to columns-* should have this class. other formatting can be different.

A few general pointers

A few generally known points I followed:

  • Prefer gap-* over margin and padding classes for flex elements.
  • Apply centering classes via flex parent. To vertically center the items, use items-center with flex-row and justify-center with flex-col. Similarly, to horizontally center the items, use justify-center with flex-row and items-center with flex-col. The change from items-center to justify-center when going from flex-row to flex-col is because the cross axis for flex-row becomes main axis for flex-col and vice versa.

Wrapping up

Tailwind CSS prefix is what I would say helped the most, other things being nice little additions that made things comfortable. That’s a few points I think were worthwile to document in case I had to do something of a similar transition in the future :)

Share this with someone who may find it useful. Thanks for reading!