Variables

Every public setting is a Sass !default variable — override it in your own abstracts/ layer (import order matters). This page lists the global axes; a component's own variables live in a Variables panel at the bottom of its page.

Many settings are also emitted as --jf-* custom properties for runtime theming, namespaced by $token-prefix (default jf). Reference one from Sass with token(x)var(--jf-x), or by its full name from CSS. Global tokens sit on :root; component tokens (--jf-card-*, --jf-chip-*, --jf-modal-*, --jf-table-*) sit on the component — override them there, not on :root (--jf-form-input-* and --jf-navbar-* stay global). Set $token-prefix: "" before import for un-prefixed names.

Sizing System

Variable Default value Description
$root-size 16px The base size that $sizing-system and $type-scale are calculated from. Fixed — no !default, so it can't be overridden. To rescale everything, override --jf-root-font-size at runtime instead.
$sizing-system (SCSS map) A map of key: value pairs — key is the size reference (0.125 – 48, in $root-size multiples), value the CSS length. Also the source for the --jf-space-* and --jf-radius-* scales. Rarely needs modifying. Sass-only — it drives get-size() and the spacing utility classes at build time and is not emitted as custom properties. Use get-size() for the fixed size of a thing (width, height, control and icon dimensions); use the --jf-space-* scale / get-space() below for flow between elements (margin, padding, gap).
$flow-step "md" Which $space-scale key drives block-flow rhythm — the bottom margin between block elements (paragraphs, lists, tables, cards…). Baked into the --jf-flow token at build; components reference it as token(flow) / var(--jf-flow). Set to any $space-scale key before import, or override --jf-flow at runtime — either leaves other uses of that step (card padding…) untouched. Replaces v4's $element-margin / $element-padding (both removed).
$scroll-offset 0 Emitted as --jf-scroll-offset and applied via scroll-padding on <html>. Set it to a sticky header's height so #fragment landings clear it — see Getting Started.
$section-space fluid(32px, 96px) Block padding on a .section band, emitted as --jf-section-space.
$section-space-tight fluid(32px, 48px) What .section.is-tight repoints --jf-section-space to.
$section-space-loose fluid(48px, 128px) What .section.is-loose repoints it to.

Spacing scale

A thin t-shirt scale for flow between elements — margin, padding, gap, gutters. Each step points at a $sizing-system step. This is the consumer/runtime face of spacing — components and utilities read these, not the raw map. Reference from SCSS with get-space(), from CSS with the full --jf-space-* name. Extend by merging $space-scale at build or setting a new --jf-space-* at runtime. For the fixed size of a thing, use get-size() instead. See these and the other axes rendered on the Design Tokens page.

TokenSass stepValue
--jf-space-3xsget-size(0.25)4px
--jf-space-2xsget-size(0.5)8px
--jf-space-xsget-size(0.75)12px
--jf-space-smget-size(1)16px
--jf-space-mdget-size(1.5)24px
--jf-space-lgget-size(3)48px
--jf-space-xlget-size(6)96px
--jf-space-2xlget-size(8)128px

Line height

Unitless leading steps for utility and component use. $root-line-height is pointed at --jf-leading-base, so the body's line-height and this scale stay in sync. Reference with get-leading(). Retune via $leading-scale.

TokenValueUse
--jf-leading-flush1lines sit flush (leading = type size) — chips, single-line inputs, icon buttons
--jf-leading-tight1.2headings
--jf-leading-snug1.35large text blocks
--jf-leading-base1.5body copy
--jf-leading-loose1.7dense small print

Font weight

The nine named weights, emitted as --jf-font-weight-*. Point --jf-font-weight-semibold (etc.) at another value to shift every use at once. Reference with get-weight(). The .weight-* / .bold utilities read these.

TokenValue
--jf-font-weight-hairline100
--jf-font-weight-thin200
--jf-font-weight-light300
--jf-font-weight-normal400
--jf-font-weight-medium500
--jf-font-weight-semibold600
--jf-font-weight-bold700
--jf-font-weight-xbold800
--jf-font-weight-black900

Border radius

A t-shirt scale, its values drawn from $sizing-system steps. Component defaults map onto it (forms/chip/accordion → sm, button/progress/modal → md, card → lg, callout → none). Reference with get-radius(). Retune the whole framework's corners via $radius-scale.

TokenSass stepValue
--jf-radius-none0
--jf-radius-xsget-size(0.125)2px
--jf-radius-smget-size(0.25)4px
--jf-radius-mdget-size(0.5)8px
--jf-radius-lgget-size(0.75)12px
--jf-radius-xlget-size(1)16px
--jf-radius-2xlget-size(1.5)24px
--jf-radius-fullpill

Border

The shared border primitives. Component --jf-{c}-border-* tokens fall back to these, so a border shorthand across the framework is var(--jf-border-width) var(--jf-border-style) var(--jf-border-color).

VariableTokenDefault
$border-width--jf-border-width1px
$border-width-strong--jf-border-width-strong2px
$border-style--jf-border-stylesolid
$border-color--jf-border-colorget-color-role(neutral, muted)

Elevation

A scale of box-shadows, each mixing --jf-shadow-color toward transparent at the step's alpha. Reference with get-shadow() or the token name. Geometry and alphas live in $shadow-scale as (geometry, alpha) tuples (a list of tuples for a stacked shadow); the hue is $shadow-color / --jf-shadow-color, set at build or on :root (dark mode).

Retint: set $shadow-color (default #0b1220) before import, override a step ($shadow-scale: ("md": (0 6px 16px, 0.2))), or override the --jf-shadow-* custom property with a full value at runtime.

Dark mode re-emits the whole scale with every layer's alpha multiplied by $dark-shadow-alpha-boost (default 4), since a light-mode drop shadow is near-invisible on the dark canvas.

Step$shadow-scale defaultUse
--jf-shadow-nonenone
--jf-shadow-xs(0 1px 2px, 0.08)hairline
--jf-shadow-sm(0 1px 3px, 0.12)raised
--jf-shadow-md(0 4px 10px, 0.14)card
--jf-shadow-lg(0 10px 24px, 0.16)popover
--jf-shadow-xl(0 20px 48px, 0.18)modal
Elevation settings
VariableDefaultDescription
$shadow-scale(SCSS map)The steps above, as (geometry, alpha) tuples — or a list of tuples for a stacked shadow. Merge to retune a step or add one.
$shadow-color#0b1220The hue every step mixes toward transparent, emitted as --jf-shadow-color. Override the variable at build or the custom property at runtime. Dark mode swaps it for $dark-shadow-color.

Motion

Durations are custom properties because prefers-reduced-motion has to zero them and that can't be done in Sass. Everything animated resolves through --jf-transition (or a --jf-duration-* step), so the reduced-motion media query switches the whole framework's motion off in one place. The motion() mixin emits <prop> var(--jf-transition). Reference steps with get-duration() / get-ease(). Durations come from $duration-scale, curves from $ease-scale (in-out is the default) — retune or add steps by merging those maps. For a one-off, redefine --jf-transition (or its parts) on the element or a scope; it cascades.

TokenDefaultReduced-motion
--jf-duration-instant0s0.01ms
--jf-duration-fast0.1s
--jf-duration-base0.2s
--jf-duration-slow0.35s
--jf-duration-slower0.5s
--jf-ease-incubic-bezier(0.4, 0, 1, 1)
--jf-ease-outcubic-bezier(0, 0, 0.2, 1)
--jf-ease-in-outcubic-bezier(0.4, 0, 0.2, 1)The default curve — what --jf-transition and get-ease() use if you don't name one.
--jf-ease-springcubic-bezier(0.35, 1.6, 0.6, 1)
--jf-transitionvar(--jf-duration-base) var(--jf-ease-in-out)0.01ms

Typography

Variable Default value Description
$type-scale (SCSS map) The type scale, in rem, emitted as --jf-font-size-*. xs / sm / base are fixed; md6xl are build-time clamp() values that slide from the previous step's size up to their own, between $fluid-min-vw and $fluid-max-vw. Extend or override entries via the map. All eleven steps and their values are tabled on Typography.
$heading-scale (SCSS map) Which $type-scale step each heading level uses:
h1: "4xl", h2: "3xl", h3: "2xl", h4: "xl", h5: "lg", h6: "md".
Resize a level with $heading-scale: ("h2": "2xl").
$type-leading (SCSS map) The line-height (a $leading-scale key) paired with each font-size step — bigger text, tighter leading. The type() mixin reads it, so setting a heading size pulls the matching line-height automatically.
$fluid-min-vw 320px Viewport width below which every fluid size sits at its floor. Independent of the layout breakpoints.
$fluid-max-vw 1240px Viewport width above which every fluid size sits at its ceiling.
$measure none Optional max line length for reading text (WCAG 1.4.8). Emitted as --jf-measure and applied as max-inline-size to p / li / dd / blockquote. Set a ch value (e.g. 66ch), or flip it on per-context at runtime via the custom property.
$font-size-adjust none Applied to html as font-size-adjust (emitted --jf-font-size-adjust). Normalises apparent text size across fonts by x-height — set a number like 0.5, from-font, or ex-height 0.53 when a swapped-in typeface reads small or large. Progressive; unsupported browsers skip it.
$root-font-size var(--jf-font-size-base) (1rem) Applied to html (output --jf-root-font-size; SCSS token(root-font-size)). Because the whole type scale is rem, overriding this one custom property scales everything proportionally — a large-print build for low-vision users is :root { --jf-root-font-size: 1.25rem }. Single value by default; the old per-breakpoint retune is gone (use your own @media).
token(leading-base) The root line-height (applied to body), pointed at --jf-leading-base (1.5). Output as --jf-root-line-height; reference with token(root-line-height). It's a var() now, so passing it to Sass maths errors — use the token. Single value everywhere; override the custom property per @media for responsive root leading.
$font-primary -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" Primary font stack.
$font-secondary token(font-primary) Secondary font stack — headings by default.
$font-monospace "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace Monospace font stack used for code tags.
$font-body var(--jf-font-primary) The font stack used for body copy.
$font-headings var(--jf-font-secondary) The font stack used for headings.
$font-weight-scale (SCSS map) The nine named weights (100–900), emitted as --jf-font-weight-*.
$heading-weight get-weight(medium) Font weight for h1-h6 tags.

Colors

Variable Default value Description
$colors (SCSS map) Family name → seed colour. Each entry's 25–1000 ramp is generated from that seed at build, so $colors: ("brand": #0b7) is the whole declaration. Pass a map of shades instead only for a hand-tuned ramp. Emitted as --jf-color-{family}-{shade}; reference from SCSS with get-color() / get-color-role(). See Theme Colours.
$color-white #ffffff Pure white, emitted as --jf-color-white and used by several SCSS functions (and the range-slider thumb border). Shouldn't be changed.
$color-black #000000 Pure black, emitted as --jf-color-black and used by several SCSS functions (and the modal backdrop). Shouldn't be changed.
$body-background-color #faf9f6 The background color for the body tag — the canvas. A warm off-white by default, so a literal-white .bg-soft panel (#fff) reads as a slightly raised surface against it. html/body paint it; components never override it. --jf-color-surface ("the background of the current context") defaults to it and is overridden — by cards, modals, menus and .bg-* sections. --jf-color-surface is registered with @property as inherits: false, so each context sets its own and a nested element can't pick up an ancestor section's surface by accident; --jf-color-text is registered inherits: true. Browsers without @property treat both as ordinary custom properties.
$soft-background-color $color-white The .bg-soft fill in light mode — one step of elevation off the canvas, not emphasised. White by default (a gentle lift against the warm off-white body). Its dark-mode counterpart is $dark-soft-background-color. Consumed by .bg-soft, a plain .modal, and the .soft component modifiers (.button.soft, .chip.soft, .progress.soft).

Output as --jf-color-bg-soft, with paired --jf-color-text-soft / --jf-color-headings-soft; jf-dark-tokens swaps all three to the opposite canvas. Override at runtime in :root { … }. The reverse-of-page surface (.bg-inverse) uses a matching set of three: --jf-color-bg-inverse, --jf-color-text-inverse and --jf-color-headings-inverse (built from $dark-body-background-color / $body-background-color, no separate setting).
$background-colors () .bg-{family} is generated for every $colors family automatically (that family at 500). This map adds extra .bg-* modifiers — key is the class suffix, value is a get-color() reference or a raw CSS colour; reusing a family name as a key overrides its auto class.

Every .bg-* modifier re-declares --jf-color-surface plus its contrast-picked --jf-color-text / --jf-color-headings, and re-emits the muted/subtle text tiers; nested cards and headings follow through inheritance.
$color-text get-color(neutral, 1000) The default color for body copy. Holds a live var(--jf-color-neutral-1000) reference by default, so it follows a runtime override of the neutral palette rather than baking a fixed value at compile time. Anywhere it needs to feed Sass colour maths instead (e.g. resolve-contrast-color()'s $color-dark argument), it's normalised back to a real color via raw-color(). You can still override it with a raw literal directly if you want a color outside the palette.

Output as --jf-color-text (reference with token(color-text)). Two derived tiers come with it: --jf-color-text-muted (captions, .text-muted) and --jf-color-text-subtle (::placeholder, .text-subtle), each a color-mix() of this toward --jf-color-surface — so they re-tint on a coloured surface.
$color-text-muted-mix 70% color-mix() ratio (in srgb) of $color-text toward --jf-color-surface. Higher = closer to full text colour = less faded. $color-text-muted-mix backs --jf-color-text-muted; $color-text-subtle-mix (60%) backs the fainter --jf-color-text-subtle. Baked at build; not a token.
$color-text-subtle-mix 60%
$color-headings-preferred get-color(neutral, role-shade(emphasis)) The default color for headings — the neutral emphasis role (700 by default). Same live-reference behavior as $color-text above; kept as a numbered get-color() rather than get-color-role() so raw-color() can still resolve it for Sass colour maths.

Output as --jf-color-headings (renamed from --jf-color-headings-preferred in v5); reference with token(color-headings). This is the contextual heading token — h1h6 read it, and a .bg-* section re-declares it.
$color-role-shades (subtle: 50, muted: 300, emphasis: 700, strong: 900) Build-time only. A role alias resolves to var(--jf-color-{family}-{shade}), and CSS can't build a property name out of another custom property — so there's no runtime switch that moves a role across every family at once. At runtime you repoint the alias itself, per family: :root { --jf-color-primary-emphasis: var(--jf-color-primary-600) }.

The semantic step-role ladder. Every palette family emits four named aliases — --jf-color-{family}-subtle, -muted, -emphasis, -strong — each pointing at the numbered shade set here, plus a bare --jf-color-{family} for the 500. Retune a role framework-wide by changing its entry — merge-friendly, so $color-role-shades: (emphasis: 600) moves that one role and leaves the other three alone. The four role names are fixed: a key that isn't one of them stops the build rather than emitting aliases nothing reads. Same shape as $dark-color-role-shades; reference in SCSS with get-color-role($family, $role) for the runtime alias or role-shade($role) for the build-time number. Roles: subtle = faint tinted backgrounds, muted = borders / low-emphasis fills / visited links, emphasis = hover & active / heading tone, strong = text on a tint / strongest headings.

Each role also gets a matching --jf-color-on-{family}-{role} companion (plus bare --jf-color-on-{family} for the 500) — the WCAG-picked text colour for that role's surface, tracking the same shade so the pair can't drift. Prefer these over a numbered --jf-color-on-{family}-50 when pairing text with a role surface.
$border-color get-color-role(neutral, muted) The shared hairline colour. Card, table and accordion borders fall back to it — --jf-card-border-color / --jf-table-border-color / --jf-accordion-border-color aren't emitted; set one to override a single component, or change this to move all three. Themed table / accordion modifiers still use their own family colour.

Output as --jf-border-color; reference with token(border-color), or token-or(card-border-color, border-color) for the component-with-fallback form. Because it holds a var() reference it can't be passed to Sass colour maths — use get-color-role() / get-color-raw() for that.
$mark-background-color #ffff9d The <mark> highlight fill. Its text colour isn't a setting — choose-contrast-color() picks it at build time and the pair is run through the contrast linter, so a custom highlight can't end up unreadable.

Output as --jf-mark-background / --jf-mark-color; reference with token(mark-background) / token(mark-color). <mark> also re-declares --jf-color-surface / --jf-color-text from them, so it's a surface in its own right and ::selection re-tints against the highlight inside it.
$code-background-color get-color-role(neutral, subtle) The shared code surface — inline code, pre and var all read these (kbd does not; it's an inverted keycap). $code-color defaults to the body text colour.

Output as --jf-code-background / --jf-code-color; reference with token(code-background) / token(code-color).
$code-color token(color-text)
$selection-background-mix 20% ::selection background is color-mix(in srgb, var(--jf-color-text) <mix>, var(--jf-color-surface)) — the text colour blended toward the current surface, so it re-tints inside .bg-* sections and stays visible on every surface (an accent tint disappears where the surface is near the accent hue). <mark> exposes its own surface/text so the selection tints against the highlight there too. $selection-color sets the selected-text colour (previously unset). Not a custom property — the mix lives in the rule so it resolves per selected element. Override the ::selection rule for a fixed colour.
$selection-color token(color-text)

Dark mode

Dark mode is a class on <html> (.jf-dark / .jf-light), then data-default-theme, with prefers-color-scheme as the fallback. In dark, the semantic tokens and the step-role aliases are repointed; the numbered primitives and their --jf-color-on-* companions are left alone. See Theme Colors → Dark mode.

Variable Default value Description
$dark-mode-enabled true Master switch. false drops the entire dark-mode block (the @media (prefers-color-scheme: dark) rules, the .jf-dark rules and the data-default-theme rules) from the compiled CSS — output size is a feature. Useful per-entry-point: a consumer can leave it on for the site build and off for an editor build. Not a token.
$dark-body-background-color #14171c The canvas colour once dark. Deliberately a hair above pure black (and not neutral-1000, which carries a blue cast). --jf-color-surface follows it; the muted / subtle text tiers re-mix against it.

Feeds --jf-color-bg inside the dark block; override --jf-color-bg in your own :root.jf-dark { … } to retune at runtime.
$dark-soft-background-color #1e222a The .bg-soft fill once dark — a hair lighter than $dark-body-background-color, so a raised panel (modal, callout, chip) still reads as lifted rather than sinking to pure black. Feeds --jf-color-bg-soft inside the dark block; the contrast linter checks both halves of the flip. Override --jf-color-bg-soft in your own :root.jf-dark { … } to retune at runtime.
$dark-color-role-shades (subtle: 800, muted: 700, emphasis: 300, strong: 200) Which numbered shade each step-role alias (and its -on-* companion) points at once dark. Background-ish roles move toward the dark end of the ramp, accent-text roles toward the light end. Applied per family by @mixin jf-dark-tokens. Merge-friendly and closed to new keys, exactly like $color-role-shades.
$dark-link-visited-color-shade 400 Visited-link text is the one place that reuses muted as a text colour rather than a background/border fill — and muted's dark shade (700, above) is tuned for the fills, too dark to read on the dark canvas. This setting repoints --jf-link-color-visited only, in dark mode, to a lighter shade that clears WCAG AA against $dark-body-background-color across the default palette. Retuning $dark-color-role-shades's muted instead would "fix" this at the cost of washing out every table-hover row, callout/accordion/form border, and modal button fill in dark mode.
$dark-shadow-color #000000 The shadow tint in dark mode (the light-mode default is $shadow-color, #0b1220). Emitted as --jf-shadow-color inside the dark block.
$dark-shadow-alpha-boost 4 Multiplier applied to every $shadow-scale layer's alpha when the dark block re-emits --jf-shadow-* — a drop shadow at the light-mode alpha barely registers on the dark canvas. Raise for heavier elevation, lower toward 1 to match light. Not a token; consumed by @mixin jf-dark-tokens via build-shadow($entry, $boost).

Anchors

Variable Default value Description
$link-color primary The palette family for links (not a colour). All three link tokens are step-role aliases of it so they flip in dark mode: --jf-link-color = emphasis, --jf-link-color-active = strong, --jf-link-color-visited = muted. Change the treatments globally with $color-role-shades (the emphasis / strong / muted entries), or per site by overriding the custom properties.

Breaking change in v5: $link-active and $link-visited have been removed — set the custom properties, or $link-color to a different family.

Breakpoints

Variable Default value Description
$breakpoints (sm: 600px, md: 900px, lg: 1200px, xl: 1800px) Flat key: px map, fixed — not overridable. Keys are the grid / visibility class namespace; values feed the media mixins.

Component variables

Each component's Sass variables and custom properties are documented in a collapsible Variables panel at the bottom of its page:

Where each component's variables are documented
ComponentKey seams
Buttons$buttons, $button-base-color, $button-hover-value, padding / size / weight, --jf-button-color-*
Chips$generate-chips, $chip-padding / -font-size / -border-*, --jf-chip-color-theme / -text
Callouts$generate-callouts, $callout-padding / -border-*, --jf-callout-bg-color / -color / -border-color / -heading-color / -link-color
Cards$card-padding, --jf-card-padding-x / -y, $card-border-radius / -width / -style, --jf-card-* (on .card)
Accordions$generate-accordion-modifiers, $accordion-padding-* / -heading-* / -border-radius, --jf-accordion-heading-*
Modals$modal-max-width / -padding / -outer-margin / -border-* / -backdrop-*, --jf-modal-max-width / -padding (on dialog.modal)
Forms$form-items, $form-accent-color, border primitives ($border-width / -style / -color / -radius), focus / label / select / range, --jf-form-input-* (global)
Progress bars$generate-progressbar, $progressbar-height / -border-radius / -indeterminate-duration, --jf-progress-bar-color / -color-unknown / -bg-color
Tables$generate-table-modifiers, $table-cell-padding / -font-size / -line-height / -responsive-breakpoint, --jf-table-* (on table)
Navbar$generate-navbar, $nav-expands, $navbar-family, link / sublink / padding / dropdown / off-canvas / hamburger, --jf-navbar-* (global)
Grid & container--jf-grid-gutter, --jf-container-max / -gutter, --jf-page-max, --jf-col-min, --jf-section-space, --jf-bleed-space

Abstracts

Variable Default value Description
$token-prefix jf Namespace applied to every CSS custom property Jellyfish emits, via the token-name() helper — so $border-color is output as --jf-border-color, the palette as --jf-color-primary-500, and so on. Reference tokens from SCSS with token(border-color) (expands to var(--jf-border-color)); from plain CSS use the full --jf-* name. Set to "" (or null) for un-prefixed --border-color names.

This one must be overridden before your first @import "jellyfish-ui/…", not in your own abstracts/__all. It's defined in abstracts/01-tools/_functions.scss and consumed as the settings layer loads (the same as the $colors palette map), so a later override lands too late.

Accessibility

Variable Default value Description
$accessibility-focus-color rgb(0, 140, 255) The color used for the outline when an element receives keyboard-focus.
$accessibility-focus-outline-width 3px The width used for the outline when an element receives keyboard-focus.
$accessibility-focus-outline-offset 2px The offset used for the outline when an element receives keyboard-focus.
$force-color-contrast-ratio true Whether to force color to black when using choose-contrast-color() if the $color-text does not have sufficient contrast.
$contrast-lint true Whether the build-time WCAG contrast linter scores the colour pairs Jellyfish generates (buttons, chips, tables, .bg-* sections, and each palette shade against its --jf-color-on-* companion). Set to false to skip the check entirely.
$contrast-lint-warn true Whether a failing pair actually prints a Sass @warn. Set to false to score silently (e.g. for tooling) without spamming the console.
$contrast-lint-threshold 4.5 The minimum WCAG contrast ratio a pair must reach before $contrast-lint-warn will report it as a failure — 4.5:1 is WCAG AA for normal text; use 3 to lint against the AA large-text exception instead (18px normal weight or ~19px/14pt bold and up).
$accessibility-button-font-weight get-weight(bold) The font weight to use for font size control buttons
$accessibility-button-color get-color(neutral, 500) The color to use for font size control buttons
$accessibility-button-hover-color token(link-color-active) The color to use for font size control buttons when they are hovered — reuses the emitted link hover token (--jf-link-color-active, itself the link family's strong role).
$accessibility-button-active-color inherit The color to use for font size control buttons when they are active
$accessibility-button-border-bottom 2px The border-width to use to denote the active setting when using font size control buttons
$accessibility-button-hover-border-color get-color(secondary) The border-color to use to denote the hovered setting when using font size control buttons
$accessibility-button-active-border-color inherit The border-color to use to denote the active setting when using font size control buttons