What's new in 5.0

Jellyfish 5.0 is a ground-up modernisation: a semantic colour system with dark mode, a full design-token layer, fluid type, a CSS Grid engine, and native <details> / <dialog> components. This page is the map — each item links to the detail.

New

New in 5.0
FeatureWhat it is
Dark modeOn by default. .jf-dark / .jf-light on <html> force a mode, data-default-theme="dark|light|system" declares the site default (ignoring the OS), and failing both, prefers-color-scheme decides. JellyfishTheme JS + [data-theme-toggle] markup persist a visitor's choice with no flash.
Semantic colour systemEvery family exposes --jf-color-{family}-{subtle | muted | emphasis | strong} role aliases and paired --jf-color-on-* text colours. Components consume roles, so they flip and re-theme for free.
Surfaces.bg-{family}, .bg-soft, .bg-inverse and .bg-base (reset to the page canvas) set a self-contained surface — background, text, headings and the muted / subtle tiers, all readable and theme-aware. Cards, callouts and modals are surfaces too.
Design tokens beyond colourSpacing, line-height, radius, border width, elevation and motion are all token scales (--jf-space-*, --jf-radius-*, --jf-shadow-*, --jf-transition…) with get-space() / get-radius() / … accessors.
Fluid typeA rem scale where md6xl are build-time clamp(), sliding with the viewport. New type($step) mixin sets size + paired line-height together.
CSS Grid engineA real .grid alongside the flex .row. Fluid .container, an optional .page cap, .bleed* full-bleed helpers, .auto-grid and .subgrid-rows.
Native accordions<details> / <summary>. Open / close, keyboard and screen-reader support are the browser's; JS is optional (events, deep-linking).
Native modals<dialog>. Focus trap, top layer and Esc are native; the script adds a close button, backdrop-click, groups and events.
Native validation states:user-invalid / [aria-invalid] style controls automatically; new .form-hint / .form-error and fieldset.is-plain.
Sections.section — a full-width band with consistent, fluid vertical space and a single seam between stacked sections.
Icons.icon + @mixin icon() — a mask-based SVG icon in the current text colour, sized to the font. Point --jf-icon at a URL.
Image ratios & fit.ratio-* on an <img> crops it; .object-cover / .object-contain utilities.
Scroll offset--jf-scroll-offset — set it to a sticky header's height so #fragment landings clear it.
Contrast linterColour pairs are scored against WCAG 2.x contrast ratios (4.5:1) at build time; a failure is a build warning.

Changed

Behaviour changes in 5.0
AreaChange
Motionprefers-reduced-motion: reduce now zeroes every framework transition (the indeterminate progress bar slows rather than stopping).
Forced coloursWindows High Contrast fixups for the masked chevron, progress bar and modal buttons.
Logical propertiesFramework CSS is writing-mode-relative, so RTL works with just dir="rtl". Spacing / border / float utilities gained logical names (physical names kept as deprecated aliases — see below).
ResetMeyer→modern reset: <img> is display: block; list-marker removal is opt-in via role="list"; box-sizing is set directly, not inherited.
Block-flow spacing$element-margin is now $flow-step--jf-flow (same 1.5rem default), applied to the same elements as before plus block media (<img> / <picture> / <video> / <audio> / <figure> / <address>), .progress and .form-row — things the aggressive reset had left bare. Removed again for object-fit images, aspect-ratio crops, .card-image, a figure's own child, and media used directly as a grid column.
Grid & row spacing.grid, .row and .auto-grid all space the same way: column-gap (--jf-grid-gutter) + row-gap (--jf-flow), a trailing --jf-flow margin so they flow like a block, and the last child of each .col stripped of its trailing margin (multi-element columns keep their internal rhythm). Drop the per-item .mbe-0 you used to need.
FloatsA block that directly contains a floated .align-* child contains the float itself — no .clearfix needed.
.containerFull-width + fluid side padding (was fixed-px with auto margins at lg / xl). Content still caps at --jf-container-max.
FormsControl font-size is max(16px, 1em) (was a hard 16px !important); <select> is width: fit-content; max-width: 100% (was 300px / 60%).
Page background$body-background-color default #fff#faf9f6 (a warm off-white).
Component tokens--jf-card-* / --jf-chip-* / --jf-modal-* / --jf-table-* are declared on their component, not :root — override them there or on a scoped selector.

Breaking changes & migration

Breaking changes and what to do
ChangeMigrate
Every custom property is namespaced --jf-*Rename --border-color--jf-border-color etc. Or set $token-prefix: "" before import to keep the un-prefixed names.
v() Sass function removedUse token($name, $fallback).
$chip-border-style removedIt only ever reached .chip.outline — the base .chip border was hard-coded solid, so setting it appeared to do nothing on a filled chip. Chip borders are now always solid; write your own border-style rule if you need otherwise.
.small removed (clashed with size modifiers)Use .font-size-small.
.bg-white and .*.white removedUse .bg-soft, .button.soft, .chip.soft, .callout.soft, .progress.soft.
.clearfix removedUsually nothing — floats self-contain now. Otherwise display: flow-root on the parent.
Grid: .offset-* and push / pull removedUse .col-start / .col-end (grid) or .order-*.
Spacing / border / float utilities renamed logical.ml/.mr/.mt/.mb.mis/.mie/.mbs/.mbe; .align-left/-right.align-start/-end. Old names still work but are deprecated — they may be dropped in later versions.
Font-size scale keys renamed-2 … 8xs, sm, base, md, lg, xl, 2xl … 6xl (Tailwind convention). Update token(font-size-*) / $font-sizes references.
$weight-* Sass variables removedUse get-weight(bold) or the --jf-font-weight-* tokens.
$element-margin / $element-padding removedBlock-flow spacing is $flow-step--jf-flow.
$global-transition / $transition-timing removedUse --jf-transition / the --jf-duration-* + --jf-ease-* scales.
$font-sizes-h1…h6 / $heading-line-height removedUse $heading-scale (which step each level uses) and $type-leading.
Colour role scalars → one map$color-subtle-shade / -muted-shade / … → $color-role-shades map.
$link-color is now a family nameprimary, not get-color(primary). $link-active / $link-visited removed — derived from $link-color's roles.
--jf-color-headings-preferred--jf-color-headings; *-fg--jf-color-on-*Rename any references.
--jf-color-section-background / -section-text / -section-headings removedRenamed to --jf-color-surface / --jf-color-text / --jf-color-headings. A .bg-* section re-declares them locally; --jf-color-surface defaults to the page canvas.
$card-border-color / $table-border-color / $accordion-border-color removedThose borders now resolve var(--jf-{c}-border-color, var(--jf-border-color)). Set the component custom property to move one, or $border-color to move all three. Themed .{family} modifiers keep their own family border.
Accordion and table colour settings removed — $accordion-heading-bg-color / -hover-bg-color / -text-color / -hover-text-color, $table-stripe-color, $table-hover-background / $table-hover-colorEach component commits to a semantic role now (rest subtle, hover muted), with text from that role's --jf-color-on-* companion. Override the paired custom properties instead — see Accordions and Tables.
$accordion-transition-duration removedAccordion motion runs on --jf-transition like everything else. Redeclare it on .accordion to change the tempo.
makeColorPalette($color, $gen-bg)makeColorPalette($color)You no longer call it at all — give $colors a bare seed colour (("brand": #0b7)) and the ramp is generated for you. An explicit map is still accepted for a hand-tuned ramp. The old second argument, which auto-generated .bg-* modifiers, is gone — a .bg-{family} is now generated for every family automatically; extra modifiers go in $background-colors.
--jf-space-3xl (192px) removedThe spacing scale tops out at --jf-space-2xl (128px). Use get-size() for a one-off larger value, or merge the step back into $space-scale.
v4 class + JS accordion removedMove to native <details class="accordion-item"> — see Accordions. name replaces data-allow-multiple; open replaces data-start-collapsed.
Modal triggeronclick="toggleModal('id')"data-modal-target="id" on a button (CSP-safe). .has-open-modal body class removed.
abstracts/02-settings/_grid.scss deleted$breakpoints is a flat constant (sm 600, md 900, lg 1200, xl 1800); $cols / $grid-has-order / $grid-has-offset / $base-* gone.
Debug overlay removed.jf-debug, jfDebug(), $debug-mode-on and debug.html are gone.

Also changed

Smaller housekeeping that shouldn't need any action:

  • Dropped the stickybits and es6-promise dependencies; lazyload-bg.js for backgrounds is kept. hamburgers is still vendored for the navbar toggle.
  • smooth() is deprecated in favour of motion(). It still compiles as an alias, so existing SCSS keeps working — switch when convenient.
  • .hide-xl fixed — it was emitted outside any media query, so it hid at every width instead of only from 1800px. It's now an alias of .hide-above-xl. If you were using it to hide something everywhere, switch to .hide. New .hide-xs closes the other end, so the band classes now cover xsxl with no gaps — see Utilities.
  • Dead .radio-control / .checkbox-control focus rules dropped — the component they styled was replaced by native accent-color back in 4.x; the rules had been shipping ever since.
  • Removed all IE-only vendor pseudo-elements (::-ms-*) and hand-written prefixes autoprefixer now manages.
  • Removed dead Sass helpers (map-deep-get, n, h, nh, hn).
  • gulp-uglifygulp-terser (handles modern JS).
  • Spacing literals snapped to the nearest scale step; a few component paddings and grid gutters shifted a pixel or two as a result.
  • ::selection, mark, figcaption / caption now set an explicit colour so they read on any surface.