Skip to content
PolyFish CSS

Changelog

Changes to the framework — the CSS modules, the optional script, the themes and the fonts. Grouped as Added, Changed, Removed and Fixed. Breaking changes are marked, and every rename is mapped in the migration guide. Changes to this website are on the blog.

Current: 0.22.0 12 CSS modules Semantic versioning

Versioning

Semantic versioning, pre-1.0. A minor release may rename a class or token; every rename lands in the migration guide. Patch releases never rename anything. Also available as CHANGELOG.md and an Atom feed.

show
Radio inputs and :has().

0.22.0#

Added · Changed · Fixed

Added

  • Classless covers the remaining text-level and structural elements: abbr[title], ins, del, dt/dd, sub/sup, caption and legend, plus hover, focus and disabled states on unclassed buttons.
  • .pf-reveal gains --left, --right and --zoom direction variants — scroll-driven entrance motion, still guarded by animation-timeline support and prefers-reduced-motion.
  • themes/sudo.css — the SudoSecurity house palette: true-black ground, hairline borders, teal accent with a violet second and Inter throughout. Eleven themes ship; polyfish.org itself wears this one.
  • Docs site: the nav checkbox now publishes aria-controls/aria-expanded through site.js, and every <main> carries tabindex="-1" so the skip link moves focus, not just scroll position.
  • New post — 'Coming from Tailwind': a ten-row map from the common utility reflexes to what PolyFish does instead, and the honest list of what does not translate.
  • Tooling: verify.py now resolves src, poster and srcset on media elements and checks that for, aria-controls, aria-labelledby, aria-describedby and aria-owns land on real ids; the browser suite pins nav aria state, ?s= deep links, pf-segment, the classless fill and pf-reveal under reduced motion.

Changed

  • 690 public classes across twelve modules.
  • Docs site: site.css ships minified as site.min.css (70 KB → 42.6 KB), and the module size tables on /docs/install are stamped by release.py from the files on disk — they had drifted while being hand-maintained.

Fixed

  • The classless module now sits directly after Core in the layer order instead of before it. :where() cannot lose to a later layer, so Core's reset had been erasing the unclassed button, field and table styles since the module shipped — bare <button> rendered transparent.
  • Examples: the palettes card's thumbnail existed only in the markup; the four immersive demos (dashboard, app-shell, docs-page, sign-in) gained a route back to the gallery, and two pages carried copy-pasted titles and descriptions.

0.21.0#

Added · Changed · Fixed

Added

  • --pf-brand-fg and --pf-brand-line — role tokens for text and rules in the mark's colours. They darken in the light theme and inside .pf-invert, so .pf-fg-brand and .pf-brand-rule hold AA everywhere.
  • Forms deepen: :disabled styling on inputs, :-webkit-autofill theming so Chrome's autofill matches the palette, and styled input[type="color"] swatches.
  • Docs site: playground presets and #play= share links, tokenised multi-word search with per-word highlighting, and a code-block Copy that exports only the lines you can see.

Changed

  • .pf-scroller smooth-snaps to anchors under prefers-reduced-motion: no-preference, so plain #slide links drive it — a pager with no script.

Fixed

  • Forced-colors mode keeps progress and meter fills, the switch knob and the range track/thumb painted in system colours instead of vanishing.

1.0.0-beta.1#

Added · Changed

Added

  • .pf-segment — a segmented control on radio inputs with no JavaScript: keyboard, focus and disabled states, plus a --block full-width variant.
  • Docs site: global search across docs, blog, examples and changelog with ?s= deep links and recent searches, heading anchors, an offline fallback served by a service worker, llms-full.txt and copy-page-as-Markdown.

Changed

  • Breaking: --pf-density defaults to 1.2 — the whole space scale, both gaps and the section rhythm, opens up 20% for a roomier default. Set --pf-density: 1 on :root to keep the 0.20 spacing.
  • --pf-leading 1.7 → 1.75 and --pf-leading-prose 1.75 → 1.8. .pf-airy moves to 1.4 so it still reads as airy against the new default.
  • The documentation is split across six pages — install, layout, theming, typography, guides, migrating — with generated sidebars, phone menus and prev/next paging. Old section URLs keep working through redirects.
  • polyfishcss/js resolves to a real ES module — import { init, toast } works in Vite, webpack and Rollup — with polyfish.d.ts for TypeScript and every CSS module importable as a subpath.

0.20.0#

Added · Changed · Removed · Fixed

Added

  • Code samples in the guide can show what they render: a CSS-only toggle under the sample reveals the live result. No frames, no script, no change to the CSP.
  • tools/gen-reference.py generates the class reference from the CSS source. The page said it was generated on every build and was not: it had drifted to 857 classes and 11 modules.
  • tools/gen-docs-nav.py and tools/gen-palettes.py: the documentation navigation and the palette comparison page are written from one list and from themes/*.css, not hand-copied into every page.
  • tools/remove-classes.py: deletes a class from the source rule by rule, dropping selectors, emptied at-rule blocks and orphaned keyframes. The 0.20 cuts were made with it.
  • PolyFishCSS-Variants.css: state variants without a build step — pf-hover-*, pf-focus-*, pf-focus-within-*, pf-active-*, pf-disabled-*, pf-group-hover-* and pf-group-focus-* across fourteen utilities, 99 classes. Hover variants sit inside @media (hover: hover) so they never fire on a touch device.
  • PolyFishCSS-Classless.css: styles unclassed semantic elements — headings, links, buttons, fields, tables, code, quotes, <details>, <dialog>. Every rule is in :where(), sits in the lowest layer, and skips any element carrying a class. Optional.
  • .pf-popover, .pf-popover--menu, .pf-popover-anchor for the native popover attribute, with anchor positioning where supported and a fixed fallback elsewhere.
  • .pf-dialog opens from command="show-modal" and closes on backdrop click with closedby="any". .pf-dialog__actions.
  • Enter and exit transitions for .pf-dialog and .pf-popover via @starting-style and transition-behavior: allow-discrete.
  • .pf-accordion animates open through ::details-content and interpolate-size; exclusive groups use the native name attribute.
  • .pf-textarea--auto — grows with its content via field-sizing: content, bounded to 4–20 lines.
  • text-wrap: pretty on p, li, dd, figcaption, blockquote.
  • --pf-shadow-lg token. .pf-shadow-lg previously read --pf-lift directly.
  • polyfish.variants and polyfish.classless in the layer order declared by every module. Classless sits directly after Core: it extends the reset for unclassed elements while still losing to every component layer.
  • Intrinsic layout primitives that respond to their container rather than the viewport: .pf-switcher, .pf-sidebar (__side, __main), .pf-cover (__main), .pf-center (--intrinsic), .pf-icon, .pf-with-icon, .pf-imposter (--contain). Tunable with --pf-switch, --pf-side, --pf-main-min, --pf-cover-min.
  • --pf-density: one number that multiplies the space scale, both gaps and the section rhythm. .pf-compact (0.8) and .pf-airy (1.25) apply it to a region.
  • Fluid space scale --pf-space-fluid-1 to -5, growing between 320px and 1440px viewports.
  • Motion tokens: --pf-ease-out, --pf-ease-in, --pf-ease-in-out, --pf-ease-spring, --pf-duration-1 to -4.
  • Derived colour roles --pf-accent-hover, --pf-accent-wash, --pf-accent-line and the --pf-accent-2-* equivalents, computed from the accent with color-mix(). A theme can now set --pf-accent alone. .pf-retint re-derives them for one region.
  • .pf-card--numbered (position-derived counter, so reordering renumbers the set) and .pf-card--media with .pf-card__media (a fixed 16:9 band, cropped not letterboxed, so a row of cards lines up whatever the image dimensions).
  • .pf-alert--inline: a one-line alert for field-level messages, where the full alert is a billboard for four words.
  • .pf-table--numeric: tabular figures aligned to the end edge, with th[scope=row] and [data-pf-text] left alone.
  • .pf-quote--pull: a centred pull quote with rules above and below, for long-form pages.
  • .pf-badge--dot: a status badge with a leading dot in its own colour — the word carries the meaning, the dot carries the scan.
  • .pf-particles: a drifting field of accent-coloured specks behind a hero or title band, built from two pseudo-element layers of radial gradients — no canvas, no script, no DOM node. Animates only transform and opacity, paints behind content, takes no pointer events, and stops still under prefers-reduced-motion. Tunable with --pf-particle-size, --pf-particle-opacity and --pf-particle-speed.
  • .pf-hero--art and .pf-hero__art for hero and header artwork, as a background image or an inline SVG, with a scrim over it so text keeps its contrast. A group marked data-pf-art-detail is dropped below 48em, where dense artwork is noise behind a headline. Ships with the eighteen SudoSecurity hub files in art/.
  • .pf-particles--mesh and .pf-particles--constellation: SVG tiles for the particle field — the triangle motif, and points with lines between them. The SVG is used as a mask over an accent fill, because a data URI cannot read a custom property and a tile with the colour baked in would ignore every theme.
  • .pf-hero--hub, with .pf-hero__assure and .pf-hero__glance: the section-landing header pattern — promise, actions, the reassurance under them, and a row of numbers saying the section is alive. The glance row is a description list, so a screen reader reads label and value as a pair rather than six loose numbers.
  • .pf-hero--panel (hero copy on a bordered surface) and .pf-hero--compact (half the vertical padding, for a second-level page).
  • .pf-footer--center (brand, columns and legal line stacked down the middle) and .pf-footer--minimal (one row, no column grid).
  • Three themes: themes/ocean.css (blue-green, cyan and indigo), themes/ember.css (warm near-black, amber and rose), themes/orchid.css (violet ground, lilac and teal). Nine themes ship now, each with a palette example page.

Changed

  • Breaking: six names fixed to the naming rule, ahead of the 1.0 freeze: .pf-none → .pf-hidden, .pf-hide-sm → .pf-hide-mobile, .pf-hide-lg → .pf-hide-desktop, .pf-display → .pf-font-display, .pf-mono → .pf-font-mono, .pf-bordered-accent → .pf-bordered-strong. The migration guide carries the table.
  • Breaking: Variants is curated rather than a cross product: 19 classes, down from 99. Kept are 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. The whole pf-disabled-* family is gone, along with combinations like a disabled lift. Variants is 1 KB, down from 11 KB.
  • 678 public classes across twelve modules, down from 926 across thirteen, with no component removed.
  • .pf-pagehead is clamp(2.5rem, 5vw, 4rem) tall instead of clamp(4rem, 8vw, 6.5rem), so a second-level page starts with its content rather than a title band. .pf-pagehead--roomy keeps the taller treatment where the title is the point.
  • .pf-section--roomy and --vast lose about a third of their padding (clamp(3.5rem, 8vw, 6rem) and clamp(4.5rem, 11vw, 8.5rem)).
  • The documentation is one long page. Installation, modules, layout, typography, tokens, theming, forms, utilities, effects, JavaScript, accessibility, performance, guides and migrating are sections of /docs, each with its own contents row; every old URL returns a 301 to its section. Components and the class reference keep pages of their own.
  • --pf-border-strong and --pf-focus derive from --pf-accent instead of fixed values.
  • 1,323 classes down to 1,003 — 42% fewer than two releases ago, with no component removed. The bundle is 19 KB gzipped.
  • 1,740 classes down to 1,001, thirteen modules, and the bundle from 20.6 KB to 18.6 KB gzipped — measured, not estimated.
  • 1,740 classes down to 1,323 in the first pass of this release.
  • The mark and both wordmarks are redrawn as a robotic betta: a turbine-blade tail fan, a swept dorsal stack, ventral blades, plate seams and a sensor visor — on the same five colours. The files also lost their embedded metadata, taking the mark from 9,006 to 2,134 bytes.
  • The hero scrim holds flat across the text band rather than thinning at its midpoint: the worst pixel behind hero text measured 5.58:1 there, and now measures 6.2:1. --pf-hero-scrim tunes it; .pf-hero--panel is the route to a 7:1 floor.
  • Default palette: neutral #181818 ground with a teal primary (#32b6af) and a purple second (#b396e8), replacing the navy-and-green scheme. Light scheme accents follow (#0f5d58, #55309c). Every pairing measures at least 7:1.
  • .pf-grid--2/3/4 treat the column count as a ceiling: a track narrower than --pf-col-min (17rem) drops a column instead. Three cards across a 987px measure left 226px tracks breaking body text every three words.
  • --pf-container is 987px, down from 1160px, with new --pf-container-narrow (720px) and --pf-container-wide tokens; .pf-container--narrow and --wide read those tokens instead of fixed widths. Wide defaults to the same 987px measure — raise the token for a broader band.
  • .pf-hero--split needs 460px per column before it splits, up from 400px. Below that the display title breaks into short lines and the panel beside it is unreadable, so the hero stacks.
  • polyfish.js builds the tablist as an inserted <span class="pf-tabs__list"> that claims the labels with aria-owns, and marks the radios aria-hidden. Previously role="tablist" went on .pf-tabs, making the radios and panels its children — invalid ARIA.
  • --pf-accent-hover and --pf-accent-2-hover mix toward --pf-text instead of black, so hovering can only raise the contrast of button text.
  • Syntax colours in .pf-code (.pf-tag, .pf-attr, .pf-str, .pf-comment) derive from the colour roles.
  • Light scheme: --pf-hue-1 #2e5816, --pf-hue-2 #7c3d00, --pf-base-300 #3b5163, bringing links, button text and muted text to at least 7:1.
  • themes/cream.css: accent #46580e (7.02:1, previously 3.96:1).
  • Inline code wraps: overflow-wrap: anywhere with box-decoration-break: clone, replacing white-space: nowrap.
  • h1, h2, h3 hyphenate below 30em.
  • Touch-target and 16px field rules under (pointer: coarse) moved from Core into the module that owns each component.
  • data-pf-dialog in polyfish.js is now a fallback: it acts only where the browser did not already open the dialog natively.
  • Hover variants are scoped to @media (hover: hover); transitions sit inside prefers-reduced-motion: no-preference.

Removed

  • Breaking: PolyFishCSS-Compat.css. It aliased the names renamed in 0.16 and 0.17; both renames are listed with their replacements in the migration guide, which is where a rename belongs. The polyfish.compat layer is gone from the layer order.
  • Breaking: duplicate width names — .pf-w-1-2, -1-3, -2-3, -1-4, -3-4, -1-5, -2-5, -3-5, -4-5, .pf-w-half and .pf-w-100. The percentage scale (.pf-w-50, .pf-w-full) says the same thing once.
  • Breaking: flex sizing duplicates .pf-basis-*, .pf-flex-auto, .pf-flex-initial, .pf-flex-none, .pf-grow-0/1, .pf-shrink-1; grid leftovers .pf-span-1..6, .pf-row-span-2 and .pf-place-*; and the responsive gap mirrors .pf-md-gap-* and .pf-lg-gap-* with their -px steps.
  • Breaking: the 22 responsive alignment, order, width and text mirrors (.pf-md-items-center, .pf-lg-order-last and the rest). Responsive visibility and display stay — .pf-md-hidden, .pf-md-block, .pf-md-flex, .pf-md-grid-d — because those genuinely change per breakpoint.
  • Breaking: from Effects, the transform family (.pf-translate-*, .pf-rotate-*, .pf-scale-*, .pf-flip-x, .pf-origin-*, .pf-transform), the filters except .pf-frost, the ring section that duplicated .pf-ring, the transition and timing extras (.pf-duration-*, .pf-delay-*, .pf-ease-*, .pf-transition-opacity/shadow/transform, .pf-will-change-*), scroll snap, blend, resize, appearance, caret, list markers, .pf-fade-*, .pf-animate-bounce, .pf-animate-slide-in and .pf-group-hide. The motion tokens they wrapped — --pf-ease-out, --pf-duration-2 and the rest — are unchanged. Effects is 26 classes, down from 109.
  • The Grid module. Its 114 classes — twelve spans across three tiers, offsets, order and row gutters — are replaced by layout primitives that carry their own thresholds: .pf-grid--2/3/4, .pf-sidebar, .pf-switcher. Nine core modules now, not ten. The components page carries the full mapping.
  • Axis and side spacing utilities: mx, my, ms-N, me-N, m-N, px, py, pt, pb, ps, pe, the gap-x and gap-y families, the -px steps, and .pf-cols-*. 194 classes. gap on a layout primitive covers what they did, which is the whole argument for gap existing; .pf-mt-*, .pf-mb-*, .pf-p-* and the auto margins stay.
  • Responsive margin and padding tiers (pf-md-mt-*, pf-lg-p-* and the rest, 60 rules). Vertical rhythm belongs to the layout primitive, not to a breakpoint-prefixed margin; responsive gap stays.
  • Twelve variant utilities that nothing varied: a second accent, an accent wash, a deep background, muted text, a strong border, plain and removed shadows, three opacity steps, an upward scale and a visibility toggle. At seven states each that was 84 classes; Variants is now 99.
  • Margin and padding utilities for individual sides and axes — .pf-mx-*, .pf-my-*, .pf-ms-*, .pf-me-*, .pf-px-*, .pf-py-*, .pf-pt-*, .pf-pb-*, .pf-ps-*, .pf-pe-*, .pf-m-* and the 1px variants. Gap and the layout primitives cover the spacing these existed for; .pf-mt-*, .pf-mb-*, .pf-p-* and the auto margins remain. 194 rules.
  • .pf-gap-x-* and .pf-gap-y-*, and .pf-cols-*, which duplicated .pf-grid--2/3/4.
  • Breakpoint tiers sm (576px), xl (1200px) and xxl (1400px) across Grid, Space and Utilities. Two tiers remain, md (768px) and lg (992px): sm mostly duplicated the base layout and the wide two never applied at the 987px measure. Raise --pf-container and need a third? A media query in your own stylesheet is three lines.
  • .pf-offset-* in every tier. A start margin — .pf-ms-auto — does the same job without 36 classes, and the whole site used one offset.
  • Scheme variants pf-dark-* and pf-light-*. The role tokens already flip with the scheme, so these only ever did what a one-line rule in your own stylesheet does.

Fixed

  • tools/release.py matched only vX.Y.Z when restamping headers, so every prerelease build appended its suffix to the last one and shipped files reading v0.19.0-rc.8-rc.8-…-rc.1. It now matches the full semver, prerelease included.
  • Components read palette tokens directly in about sixty places, so on any theme that did not redeclare them the primary button hovered to the default green and accent cards, badges and washes stayed green. Every component now reads roles only.
  • --pf-ring was a fixed green, so focus rings ignored the theme. It now uses --pf-accent-line.
  • Link underlines, inline code borders, .pf-card__icon borders and the mobile tap highlight used literal copies of the default accent. They now derive from --pf-accent.
  • tools/release.py had a hand-written module list that omitted Grid, so that module was never minified into the bundle and a page loading the bundle got its markup unstyled while every check passed. The release script now compares the list against the module files on disk and refuses to run if one is missing.
  • .pf-checks and .pf-steps list items were two-column grids, so any inline element inside them — a <code> chip, a link — became a grid item of its own and was dropped into the narrow marker column, where it wrapped one character per line. Both markers are positioned now and inline content stays inline.
  • .pf-row inherited the page gap for its column gutter. With a larger gap, eleven gutters between twelve tracks were wider than a 320px screen and every track collapsed to zero; the row now has its own gutter, overridable with --pf-gutter-x.
  • .pf-invert never repainted a component's own background: its paint rule sat in the polyfish.core layer while .pf-card's background sits in polyfish.content, a later layer, so an inverted card kept its dark surface and flipped its text to dark — 2.5:1. The flip is now painted from the utilities layer.
  • .pf-invert kept the page's accent, leaving a dark-scheme accent on a light panel. It now flips --pf-accent, --pf-accent-2, --pf-ink, --pf-focus and the derived hover, wash and line colours.
  • .pf-btn read --pf-base-950 for its text instead of --pf-ink, so any scope that flipped the ink — .pf-invert, .pf-retint — got dark text on a dark button.
  • .pf-footer--accent painted itself with the accent without flipping --pf-text and --pf-text-muted, leaving muted text at 1.19:1 on the accent background.
  • The mobile-menu checkbox stayed in the tab order above the 860px breakpoint, where its label is hidden: a focusable unlabelled control on every desktop page.
  • .pf-table td[data-pf="no"] used a faded copy of the muted colour at 3.7:1; it now uses --pf-text-muted.
  • The breadcrumb separator and the scroll-fade gradient used literal palette colours instead of roles.
  • themes/cream.css: second accent #8e3509 (7.01:1, previously 3.6:1). themes/dusk.css: second accent #f07e79 (7.02:1, previously 6.95:1).
  • The 16px field floor on touch devices had no effect since 0.17: it sat in the polyfish.core layer and Content's field rule, in a later layer, overrode it, so iOS zoomed on focus.
  • .pf-pagination__item was 40px on touch; now 44px.
  • .pf-alert--success, --warn and --danger used border-left-color, colouring the wrong side under dir="rtl".
  • Single-column grids — .pf-stack and 25 others — grew to their widest child's minimum content and overflowed narrow screens. Their children can now shrink.
  • .pf-pagehead__inner and .pf-section__head let a long single-word heading widen the column.
  • The short-landscape media query reset section padding and --pf-gap-lg without --pf-density.
  • --pf-ink was declared only in the optional PolyFishCSS-Compat.css, so without it pf-*-bg-accent variants and classless buttons set no text colour. It is now a Core role.
  • Field placeholder colour was a literal copy of the default muted colour; it now derives from --pf-text-muted.

0.19.0#

Added

Added

  • themes/paper.css — editorial light palette, serif display face, no radius.
  • themes/mono.css — terminal dark palette, monospace display face, square corners.

0.18.0#

Added · Changed

Added

  • Metric-matched fallback faces in PolyFishCSS-Fonts.css: Inter Fallback, Bricolage Fallback, Plex Mono Fallback, with ascent-override, descent-override, line-gap-override and size-adjust measured from the shipped woff2. Reduces layout shift on font swap.
  • .pf-no-print, .pf-print-only.

Changed

  • Font stacks name the metric-matched fallback before generic families.
  • Print stylesheet rewritten: forces a light palette, hides navigation and chrome, expands tab panels and accordions, prints external link targets, sets page-break rules.

0.17.0#

Added · Changed

Added

  • Every module wraps its rules in @layer polyfish.<module> and declares the full layer order.
  • Right-to-left support throughout.

Changed

  • All physical properties replaced with logical equivalents: margin-inline-*, padding-inline-*, border-inline-*, inset-inline-*, text-align: start|end.
  • Breaking: .pf-ml-*, .pf-mr-*, .pf-pl-*, .pf-pr-* renamed to .pf-ms-*, .pf-me-*, .pf-ps-*, .pf-pe-* (including responsive variants). .pf-text-left, .pf-text-right renamed to .pf-text-start, .pf-text-end. Aliased in PolyFishCSS-Compat.css.

0.16.0#

Added · Changed

Added

  • PolyFishCSS-Compat.css — aliases for renamed tokens and classes. Kept until 1.0.
  • Font licences (SIL OFL 1.1) for all bundled faces in fonts/.
  • package.json with per-module exports.

Changed

  • Breaking: palette tokens renamed by position. --pf-blue-{900..600} → --pf-base-{900..600}; --pf-paper → --pf-base-50; --pf-mist → --pf-base-300; --pf-ink → --pf-base-950; --pf-green* → --pf-hue-1*; --pf-orange* → --pf-hue-2*.
  • Breaking: colour-named helpers renamed by role: .pf-fg-green → .pf-fg-accent, .pf-bg-green-wash → .pf-bg-accent-wash, .pf-btn--orange → .pf-btn--accent-2, .pf-pill--green → .pf-pill--accent, .pf-footer--green → .pf-footer--accent, and seven more. Aliased in Compat.

0.15.0#

Fixed

Fixed

  • .pf-steps: children after the first rendered in the 2.2rem number column. All children now placed in column 2.

0.14.0#

Added

Added

  • .pf-text-2xl, .pf-text-3xl, .pf-text-4xl, .pf-text-5xl.

0.13.0#

Changed · Fixed

Changed

  • Background ramp darkened: --pf-base-900 #00030f, --pf-base-800 #000823, --pf-base-700 #000f3f, --pf-base-600 #17306e.

Fixed

  • Light-mode surface tints, .pf-hero--photo gradient and gallery overlay used a hardcoded legacy navy instead of palette tokens.

0.12.0#

Added · Changed

Added

  • .pf-prose vertical rhythm from the space scale.

Changed

  • --pf-accent #a9cc9a → #8fe06a; --pf-hue-1-deep #87ab79 → #6dc44a.
  • --pf-section-pad, --pf-gap, --pf-gap-lg, --pf-space-7..9 increased. Hero, page-head, card, step and footer padding follow.
  • .pf-stack gap reads --pf-gap.

0.11.0#

Added

Added

  • --pf-brand, --pf-brand-2, --pf-brand-deep; .pf-brand-well, .pf-fg-brand, .pf-brand-rule.

0.10.0#

Added

Added

  • Proportional widths: .pf-w-0 to .pf-w-100 in steps of 5, plus .pf-w-1-2, -1-3, -2-3, -1-4, -3-4 and fifths.

0.9.0#

Added · Changed

Added

  • PolyFishCSS-Effects.css: composable transforms, filters, .pf-frost, gradients, .pf-gradient-text, rings, six animations, transition utilities, scroll-snap, .pf-group hover, blend and isolation. 92 rules.

Changed

  • Animations are defined only inside prefers-reduced-motion: no-preference.

0.8.0#

Changed

Changed

  • Background ramp darkened; --pf-paper #e9eefa, --pf-mist #a9bcd8, --pf-ink #00081f.

0.7.0#

Added

Added

  • .pf-drawer, .pf-bottombar, .pf-has-bottombar, .pf-toast.
  • .pf-table--stack, reading cell labels from data-pf-label.

0.5.0#

Added · Removed · Fixed

Added

  • PolyFishCSS-Space.css: padding, margin, gap, grid tracks, spans, placement and flex sizing at four breakpoints.
  • .pf-scroller.
  • env(safe-area-inset-*) on container gutters, mobile menu and footer; touch-action: manipulation on interactive elements.

Removed

  • Spacing, margin and gap utilities from Utilities; now owned by Space.

Fixed

  • Form fields floored at 16px under pointer: coarse to prevent iOS focus zoom.
  • Mobile menu capped at 100dvh and scrollable.
  • min-height: 100vh paired with 100dvh.
  • .pf-menu popover width capped to the viewport.
  • .pf-tabs strip scrolls horizontally below 620px.

0.4.0#

Added

Added

  • polyfish.js: data-pf-menu, data-pf-tabs, data-pf-dialog, data-pf-copy, data-pf-counter, data-pf-dismiss, data-pf-sort, data-pf-spy, data-pf-theme-toggle; PolyFish.init(root).
  • .pf-code__copy, .pf-th-sort — styles for elements the script creates.

0.3.0#

Added · Changed

Added

  • PolyFishCSS-Forms.css.
  • Automatic light mode via prefers-color-scheme; data-pf-theme to pin.
  • Container-query helpers: .pf-container-q, .pf-cq-row, .pf-cq-2..4, .pf-cq-side.
  • Icon and link buttons, aria-busy loading state, .pf-stretched-link, shadow scale, divide utilities, table variants.

Changed

  • Validation styling keys off aria-invalid and :user-invalid.

0.2.0#

Added · Changed

Added

  • PolyFishCSS-Grid.css: twelve columns at five breakpoints, offsets, order, gutters.
  • PolyFishCSS-Components.css.
  • Responsive utility variants using infixes (.pf-md-hidden).

Changed

  • Breaking: flex-direction helpers renamed .pf-flex-col / .pf-flex-row; .pf-col now belongs to Grid.
  • Breaking: removable chip renamed .pf-tag → .pf-chip.

0.1.0#

Added

Added

  • Core, Headers, Content, Footers, Utilities.