| File | Covers | Size | Needs Core |
|---|---|---|---|
| Core | Tokens, reset, type, layout, buttons | 11 KB | Is Core |
| Grid | Twelve-column responsive grid | 13 KB | Yes |
| Headers | Top bar, nav, heroes, page headers | 7 KB | Yes |
| Content | Sections, cards, tables, forms, code | 12 KB | Yes |
| Forms | Floating labels, validation, range, file | 5 KB | Yes |
| Components | Badges, tabs, menus, lists, dialogs | 13 KB | Yes |
| Footers | Footer layouts and link columns | 4 KB | Yes |
| Fonts | Self-hosted @font-face declarations | 4 KB | Independent |
| Space | Padding, margin, gap and grid utilities | 20 KB | Yes |
| Effects | Transforms, filters, gradients, animations | 6 KB | Yes |
| Utilities | Spacing, colour, visibility helpers | 4 KB | Yes |
What you get for what you load
Tick the modules you would link. Every component below that needs one you have not ticked is marked unavailable — this is the framework's dependency graph, made pokeable. Core is not a checkbox because nothing works without it.
Buttons, type, layout
Every button variant, the type scale, container, stack, cluster, grid and split.
Core — always onNav, hero, page head
Announcement bar, sticky navigation with the mobile menu, four hero variants, breadcrumbs.
needs HeadersSections, cards, tables
Section rhythm, cards, plans, stats, tables, alerts, code blocks, accordions, sidebars.
needs ContentFloating labels, validation
Input sizes, floating labels, feedback messages, fieldsets, range, file inputs, option cards.
needs FormsTabs, menus, dialogs
Badges, button groups, pagination, progress, lists, avatars, switches, tabs, menus, dialogs, toasts.
needs ComponentsTwelve columns
Explicit column spans, offsets and order across five breakpoints.
needs GridPadding and margin utilities
Every side and axis, gaps, grid tracks, flex sizing, four responsive breakpoints.
needs SpaceTransforms and animation
Transforms, filters, gradients, rings, six animations, scroll snap, group hover.
needs EffectsCheckboxes and :has(). A dimmed tile is a component you would be writing markup for that has no styles behind it.
Core
The only required file. It declares every custom property the others read, resets the document, sets the type scale, and provides the layout primitives and buttons.
- Layout:
.pf-container,.pf-stack,.pf-cluster,.pf-grid,.pf-split,.pf-shell - Brand:
.pf-logo,.pf-lockup - Buttons:
.pf-btnwith--secondary,--ghost,--orange, three sizes,--block,--square - Marks:
.pf-pill,.pf-mark,.pf-dot,.pf-facet - Accessibility:
.pf-skip,.pf-visually-hidden, a global:focus-visiblering, and a reduced-motion block
Grid
A twelve-column grid with five breakpoints — .pf-row, .pf-col-8,
.pf-col-md-4, offsets, order and per-row gutters — for the layouts where the
proportions themselves change per breakpoint.
Skip it for most pages. .pf-grid--3 is one class and handles its own
breakpoints; a column system is two classes per child and handles them by hand. The module
exists because some designs genuinely need the control, not because every page does.
Headers
Everything above the fold. The navigation's mobile menu is a checkbox and a sibling selector, so the module needs no script.
.pf-topbar— announcement strip, plus a--greenvariant.pf-nav— sticky and blurred by default;--staticand--flushvariants.pf-hero—--split,--centerand--photovariants, with the mesh background masked in.pf-pageheadand.pf-breadcrumbfor interior pages
See it in isolation on the headers example.
Content
The largest module, covering everything between the header and the footer.
- Sections and section heads, eyebrows, ledes
- Cards, feature grids, checklists, plan cards, stats
- Tables that scroll horizontally rather than squashing
- Forms — inputs, selects with a styled arrow, textareas, checkboxes, inline forms
- Alerts, quotes, code blocks, accordions built on
<details>, galleries, steps and CTA bands
See it in isolation on the page core example.
Forms
Content styles four controls. Forms handles everything a real form needs after that: input sizes, floating labels, validation states and feedback messages, fieldsets and legends, range sliders, file inputs, selectable option cards, form layout rows and character counters.
Two decisions worth knowing about. Validation styling hangs off aria-invalid
rather than a class, so the visual state and the announced state cannot disagree. And it
uses :user-invalid rather than :invalid — the latter matches an
empty required field on page load, which paints a form red before anyone has typed a
character.
Components
Eighteen pieces for the screens behind a login: badges and tags, button groups, pagination, progress bars and segmented meters, spinners, list groups, avatars and stacks, switches, input groups, tabs, disclosure menus, dialogs, tooltips, ratio boxes, skeletons, empty states, dividers and toolbars.
Still nothing required. Tabs are radio inputs, the menu is a <details>,
the dialog is a native <dialog> with a :target fallback. Two
components carry an honest limit in their source comments — the menu does not close on an
outside click, and the tabs announce as a radio group rather than a tablist. Both need a
listener to go further, and the framework does not pretend otherwise.
Footers
Three footers in 4 KB: the column footer, a one-line --slim variant for docs and app shells, and a full-bleed --green variant that recolours its own links, social row and back-to-top link.
See it in isolation on the footers example.
Fonts
Seven @font-face rules pointing at /fonts, covering the three
families Core names. Independent of every other module — load it or don't, before Core or
after, it only declares faces. Skipping it falls back to system stacks with no layout change.
Self-hosting is a security decision before it is a performance one: with no font CDN in the page, the Content-Security-Policy can refuse remote origins outright.
Space
The full spacing surface: padding and margin on every side and axis, gaps, grid track
shorthands, flex sizing and placement, with the six most-used families repeated at four
breakpoints. .pf-px-4, .pf-mt-6, .pf-md-py-8.
The suffix is a step on the space scale, not a pixel value, so retuning
--pf-space-* retunes every utility with it. Negative margins are deliberately
absent — a negative margin is nearly always a layout fighting its container, and a utility
makes it easy to reach for twice.
It is the largest module at 20 KB minified, which is the honest cost of a utility surface with no compiler to purge it. It gzips to 2.8 KB because the strings repeat, and nothing else depends on it: if you would rather not carry it, do not load it.
Effects
Transforms composed through custom properties so translate, rotate and scale can be
combined without the last declaration silently winning. Filters and a @supports-guarded
frosted panel. Gradients built from role tokens, so they follow a theme. Rings with a real
offset. Six named animations, all opt-in.
It also carries the pattern a utility framework needs and CSS has no shorthand for:
.pf-group plus .pf-group-show, a child reacting to its parent's
hover or focus. That reveal is scoped to (hover: hover) — on a touch device the
affordance stays visible rather than hiding behind a state a finger cannot enter.
Every animation sits inside prefers-reduced-motion: no-preference rather than
merely being slowed by Core's global block. An animation that starts at opacity: 0
and is slowed to nothing leaves the element invisible forever; not applying it at all is the
only correct behaviour.
Utilities
Single-purpose helpers reading the same tokens: margins and gaps on the 4px scale, flex alignment, text sizes, role colours, two responsive visibility classes and a print block that hides navigation, footers and CTA bands.
This is the first file to drop if your project already has its own utilities — nothing else depends on it.
Rule of thumb
If you cannot point at the element on your page that needs a module, don't load it. A sign-in screen needs Core and Content; a docs page needs Core, Headers and Content.
Next: the token reference.