Migrating to 0.20
Class by class from Bootstrap, Tailwind and earlier PolyFish releases, and what has no equivalent.
01 / 01
Migrating
Coming from Bootstrap, Tailwind or a classless framework: what maps onto what, what deliberately has no equivalent, and an order of work that does not stall halfway.
Coming from another framework, most of the work is unlearning rather than learning. The tables below map what you already know onto what exists here, and name the places where there is deliberately no equivalent.
From Bootstrap
| Bootstrap | PolyFish | Note |
|---|---|---|
.container | .pf-container | One measure, 987px, plus --narrow |
.row / .col-md-6 | .pf-grid.pf-grid--2, or .pf-sidebar for unequal halves | The twelve-column system was removed in 0.20 — the primitives carry their own thresholds |
.btn .btn-primary | .pf-btn | Primary is the default; --secondary, --ghost for the rest |
.card / .card-body | .pf-card / .pf-card__body | Also --numbered, --media, --facet |
.alert-warning | .pf-alert.pf-alert--warn | --inline for a one-liner |
.table-striped | .pf-table--zebra | Wrap in .pf-table-wrap |
.badge | .pf-badge | --dot for status |
.d-flex .gap-3 | .pf-cluster | Wrapping row with a shared gap |
.modal + JS | <dialog class="pf-dialog"> | Opens from markup with invoker commands |
data-bs-toggle="tab" | .pf-tabs with radios | Works with no script; the optional script adds ARIA |
| Sass variables | Custom properties | Change at runtime, no rebuild |
No equivalent, on purpose: a carousel, a JavaScript grid system, utility classes for every property, and jQuery-era data attributes for behaviour the platform now does itself.
From Tailwind
The mental shift is larger. Tailwind composes a component out of dozens of atoms in the markup; here a component is one class and the atoms exist only for the gaps between components.
| Tailwind | PolyFish |
|---|---|
flex flex-col gap-4 | .pf-stack |
flex flex-wrap items-center gap-2 | .pf-cluster |
grid grid-cols-3 gap-6 | .pf-grid.pf-grid--3 |
mx-auto max-w-5xl px-4 | .pf-container |
rounded-lg border bg-white/5 p-6 | .pf-card |
hover:bg-emerald-500 | .pf-hover-bg-accent (Variants) |
dark:text-white | Roles flip with the scheme; no per-class variant needed |
@apply | Write the rule. There is no build step to apply into |
tailwind.config.js | :root custom properties |
What you gain: no compiler, no purge step, markup you can read aloud, and a theme that changes at runtime. What you give up: the enormous atomic vocabulary. If you want a utility for every property, keep Tailwind — that is a real preference, not a mistake.
From Pico or another classless framework
Load PolyFishCSS-Classless.css and your existing semantic HTML gets styled
with no classes at all. It sits in the lowest layer, so the moment you add a
pf- class, that class wins. That makes the migration incremental: start
classless, add components where you need more than the defaults.
A migration that does not stall
Load PolyFish after your current framework
Both will fight for a while. Keep your old stylesheet last so nothing breaks visually on day one.
Move the tokens first
Map your brand colours onto
--pf-accent,--pf-bgand--pf-text. The whole framework follows immediately.Convert page furniture next
Header, footer, containers and sections. These are the least risky and the most visible.
Then components, page by page
Cards, tables, forms. Delete the old classes as you go rather than leaving both.
Drop the old stylesheet and measure
Check contrast and check the page at 320px. Both are where migrations leave debris.
Renamed since you last looked
Pre-1.0, a minor release may rename or remove things. Every change is listed here with its replacement, and the class reference always lists the current name. Renames from 0.16 and 0.17 are in the token table.
Renamed in 0.20
Six classes renamed to the rule the rest of the framework follows, before the API freezes for 1.0.
| Was | Use | Why |
|---|---|---|
.pf-none | .pf-hidden | Base of the pf-md-hidden/pf-lg-hidden family. |
.pf-hide-sm | .pf-hide-mobile | Hides below the 860px nav breakpoint, not the sm tier its name implied. |
.pf-hide-lg | .pf-hide-desktop | Same, above it. |
.pf-display | .pf-font-display | A font-family utility named like a display utility. Now matches --pf-font-display. |
.pf-mono | .pf-font-mono | Matches --pf-font-mono. |
.pf-bordered-accent | .pf-bordered-strong | It always set --pf-border-strong; the name lied. |
Removed in 0.20
The aliases file is gone, so these need an edit rather than a compatibility link. Every removal has a one-for-one replacement except where the note says otherwise.
| Was | Use | Note |
|---|---|---|
PolyFishCSS-Compat.css | — | The alias file for the 0.16 and 0.17 renames. Rename to the current names instead; the tables above list them. |
.pf-w-1-2, -1-3, -2-3, -1-4, -3-4, -1-5 … | .pf-w-50, .pf-w-35, .pf-w-65, .pf-w-25, .pf-w-75, .pf-w-20 | Two names for one width. The percentage scale stays. |
.pf-w-100, .pf-w-half | .pf-w-full, .pf-w-50 | Same. |
.pf-md-gap-*, .pf-lg-gap-* and the -px steps | .pf-gap-* | A gap that changes at a breakpoint is what the layout primitives already do intrinsically. |
.pf-basis-*, .pf-flex-auto, .pf-flex-initial, .pf-flex-none, .pf-grow-0/1, .pf-shrink-1 | .pf-flex-1, .pf-grow, .pf-shrink-0 | Six ways to say three things. |
.pf-span-1..6, .pf-row-span-2, .pf-place-* | .pf-span-full, .pf-grid--2/3/4, .pf-items-* with .pf-justify-* | Remains of the grid system. |
Responsive alignment, order, width and text mirrors (.pf-md-items-center, .pf-lg-order-last …) | The base utility, or a container query | 22 classes. Responsive visibility and display stay: .pf-md-hidden, .pf-md-block, .pf-md-flex, .pf-md-grid-d. |
Transform utilities: .pf-translate-*, .pf-rotate-*, .pf-scale-*, .pf-flip-x, .pf-origin-*, .pf-transform | A transform in your own stylesheet | A static transform is one declaration and is almost always part of a component, not a page-level helper. |
Filters: .pf-blur*, .pf-grayscale, .pf-saturate, .pf-desaturate, .pf-bright, .pf-dim, .pf-backdrop-blur*, .pf-filter-none | .pf-frost, or your own filter | .pf-frost is the one that needed the fallback work; the rest are a single declaration. |
.pf-ring-1, .pf-ring-2, .pf-ring-accent, .pf-ring-danger, .pf-ring-offset | .pf-ring, .pf-focus-ring | The ring section duplicated the ring utility. |
Transition and timing extras: .pf-duration-*, .pf-delay-*, .pf-ease-*, .pf-transition-opacity/shadow/transform, .pf-will-change-* | .pf-transition, .pf-transition-colors, and the motion tokens | The tokens (--pf-ease-out, --pf-duration-2) remain and are the supported way to time your own transitions. |
Scroll snap: .pf-snap-* | Your own scroll-snap-type | Nothing on the site used them and snap needs per-case tuning. |
.pf-blend-*, .pf-resize-*, .pf-appearance-none, .pf-caret-accent, .pf-list-disc, .pf-list-decimal, .pf-fade-bottom, .pf-fade-right, .pf-animate-bounce, .pf-animate-slide-in, .pf-group-hide, .pf-focus-border, .pf-hover-border, .pf-hover-bright, .pf-max-w-none | Your own declaration, or the nearest kept helper | One-declaration helpers nothing reached for. |
Variant cross-product: .pf-disabled-*, and most .pf-hover-, .pf-focus-, .pf-active- and group combinations | The curated nineteen | Kept: hover background, foreground, border, underline, shadow and lift; focus and focus-within ring; active sink and scale-down; group-hover and group-focus foreground and lift. |