Button
Tag-and-class component. The framework styles bare <button>
and any element with the .button class identically. Variants
use the .is-* modifier scheme shared with Card.
Live
Combinations
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
<button class="button">Default</button>
<button class="button is-primary">Primary</button>
<button class="button is-success">Success</button>
<button class="button is-warning">Warning</button>
<button class="button is-danger">Danger</button>
</div> @use '@adnap/krysalicss' with (
$feature-list: ('base-reset', 'base-global', 'element-button')
); Modifiers
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
<button class="button is-primary">Primary</button>
<button class="button is-primary is-inverted">Primary inverted</button>
<button class="button is-primary is-outlined">Primary outlined</button>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem;">
<button class="button is-danger">Danger</button>
<button class="button is-danger is-inverted">Danger inverted</button>
<button class="button is-danger is-outlined">Danger outlined</button>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem;">
<button class="button is-link">Link</button>
<button class="button is-link" disabled>Link disabled</button>
</div> @use '@adnap/krysalicss' with (
$feature-list: ('base-reset', 'base-global', 'element-button')
); Variables
| Variable | Default | Notes |
|---|---|---|
$selector | 'button, .button' | Re-scope to '.app .btn' for non-intrusive use. |
$padding-y | 0.625rem | Vertical padding. Sized so rendered button height clears WCAG 2.5.5 AAA (44 px). |
$padding-x | $size-normal | Horizontal padding. |
$min-width | 2.75rem (44 px) | WCAG 2.5.5 AAA touch-target floor on the horizontal axis. Override to 0 for inline dense toolbars; you accept the AA 24 × 24 px floor. |
$border-radius | $global-border-radius (5px) | Set to 999px for pills. |
$inverted-selector | '.is-inverted' | Reverses (bg, fg) on hover. |
$outlined-selector | '.is-outlined' | Transparent background, themed border + foreground. |
$link-selector | '.is-link' | Renders the button as a link surface: transparent background + border, --kc-link text, --kc-link-hover on hover. |
$disabled-opacity | $global-disabled-opacity (0.6) | Faded opacity applied to :disabled, paired with cursor: not-allowed. |
$focus-outline-width | $global-focus-outline-width (2px) | Width of the :focus-visible outline; clears WCAG 2.4.11. |
$focus-outline-style | $global-focus-outline-style (solid) | Stroke style of the focus outline. |
$focus-outline-offset | $global-focus-outline-offset (2px) | Gap between the button border and the focus ring. |
$hover-brightness | $global-hover-brightness (0.95) | filter: brightness() factor applied on hover; tuned to preserve AA contrast across shipped combinations. |
See Combinations and light variants for $enable-light, $default-combination, and $controls — cross-cutting plumbing common to every theme-aware component.
Override example
// Exhaustive override: every variable the button module exposes.
// Drop the keys you don't need — defaults are inherited from the
// framework globals (`$global-*`) and the default colour combination.
@use '@adnap/krysalicss/element/button' with (
// Selector contract. Re-scope to avoid styling bare `<button>` (e.g.
// when embedding the framework inside a host app's chrome).
$selector: 'button, .button',
$inverted-selector: '.is-inverted',
$outlined-selector: '.is-outlined',
$link-selector: '.is-link',
// Sizing. Defaults are tuned so rendered height clears WCAG 2.5.5 AAA
// (44 × 44 px). Shrink `$min-width` to 0 only if you accept the AA
// 24 × 24 px floor.
$padding-y: 0.625rem,
$padding-x: 1rem,
$min-width: 2.75rem,
$border-radius: 999px,
// (background, foreground) tuple applied to a bare `.button` with no
// `.is-*` modifier. Keep it themed-token-friendly if you author your
// own theme.
$default-combination: (#ffffff, #1a1a1a),
// Focus-ring tuning — must stay visible against every combination
// your theme ships.
$focus-outline-width: 2px,
$focus-outline-style: solid,
$focus-outline-offset: 2px,
// Hover scale (`filter: brightness()`) and disabled fade.
$hover-brightness: 0.92,
$disabled-opacity: 0.6,
); Open this override in playground →
Tokens consumed
| Token | Used for |
|---|---|
--kc-default-bg / --kc-default-fg | Plain .button (no .is-*). |
--kc-{label}-bg / --kc-{label}-fg | Each combination modifier (primary, warning, danger, success, light). |
--kc-link / --kc-link-hover | .is-link rest + hover text colour, matching the <a> typography rules. |
--kc-focus-ring | :focus-visible outline colour. Falls back to --kc-fg then currentColor if a theme omits it. |
Touch-target sizing: WCAG 2.5.5 (AAA).
Default $padding-y + $min-width ensure every
button renders at ≥ 44 × 44 CSS pixels: the AAA floor for pointer-input
targets. The AA floor is 24 × 24 px (WCAG 2.5.8); if you ship inline
dense toolbars and accept AA, override $min-width to
0 and reduce $padding-y in your
@use ... with (...) invocation. Don't shrink globally:
the rest of the framework (focus-ring contrast, padding rhythm) is
calibrated against the AAA target.
Contrast: .is-inverted.
For non-default combinations, the modifier flips the button onto the
page surface: --kc-bg as fill, the combination's
--kc-<label>-bg as text and border. Contrast then
comes down to the chosen combination colour against the theme's page
bg — light, mid-luminance combos (.is-warning) will
fail WCAG AA on a white page; reserve them for your own
surface-colour overrides. .is-default.is-inverted and
plain .is-inverted do a true (bg, fg)
swap of the default combination tokens (--kc-default-fg
becomes the fill, --kc-default-bg becomes the text +
border) so they stay visible on either theme.
Contrast: .is-outlined.
The outlined modifier paints palette-literal colours (not theme
tokens), so the same hex sits on every page background you ship.
On the default light theme, .is-primary,
.is-warning, .is-danger and
.is-success clear WCAG 1.4.3 AA against white. On the
default dark theme, those same literals can fall below AA against
the near-black page surface — a documented trade-off in favour of
predictable cross-theme appearance. If your dark theme needs
strict AA outlined buttons, scope a custom .button
selector with theme-aware colour overrides.