Numbered navigation strip. Flex row of .pagination__link
children flanked by optional prev/next slots and an ellipsis slot for
collapsed page ranges. The current page reads from the framework's
primary colour combination; disabled prev/next reuse the global
disabled-control treatment.
The component is markup-flexible: the numbered list accepts either
.pagination__list, <ol>, or <ul> — all three render identically.
.pagination__previous and .pagination__next sit outside the list so
the flex order (prev / list / next) is preserved while still letting
the list wrap independently at narrow widths.
Both the WAI-ARIA contract and a class-only fallback are emitted for
every state, so static-site generators and accessibility-correct
templates render identically.
State
ARIA hook
Class hook
Notes
Current page
aria-current="page"
.is-current
Pulls the primary combination from the framework's colour map. Hover affordance disabled (already painted).
Disabled prev/next
[disabled] / aria-disabled="true"
.is-disabled
Routes through the global disabledControl() mixin. Hover affordance stripped.
Modifiers
Modifier
Effect
.is-rounded
Pill links — radius bumps to $global-max-border-radius.
.is-centered
justify-content: center on the outer flex row so prev/next align with the numbered links.
.is-right
justify-content: flex-end.
.is-small
Bumps font-size and link min-width to the small size tier.
.is-large
Bumps font-size and link min-width to the large size tier.
Variables
Variable
Default
Notes
$selector
'.pagination'
Root <nav>.
$list-selector
'.pagination__list'
Optional inner list class; <ol> / <ul> also matched.
$link-selector
'.pagination__link'
Numbered link.
$previous-selector
'.pagination__previous'
Previous-page anchor / button.
$next-selector
'.pagination__next'
Next-page anchor / button.
$ellipsis-selector
'.pagination__ellipsis'
Non-interactive gap glyph for collapsed page ranges.
$current-selector
'.is-current'
Class-only equivalent of aria-current="page".
$disabled-selector
'.is-disabled'
Class-only equivalent of [disabled] / aria-disabled="true".
$rounded-selector
'.is-rounded'
Pill-shape modifier.
$centered-selector
'.is-centered'
Center the outer flex row.
$right-selector
'.is-right'
Anchor the outer flex row to flex-end.
$small-selector
'.is-small'
Small size tier.
$large-selector
'.is-large'
Large size tier.
$gap
$size-extra-small
Gap between links and between rows on wrap.
$min-width
2.5rem
Per-link minimum width AND height — keeps numeric pages square. See WCAG 2.5.5 note below.
$padding-y
$size-extra-small
Vertical padding.
$padding-x
$size-extra-small
Horizontal padding.
$border-radius
$global-border-radius
Link radius. Overridden to $global-max-border-radius under .is-rounded.
$border-mix
35%
Border tint relative to --kc-fg on numeric links and (when $nav-ghost: false) the nav slots. Clears WCAG 1.4.11 (3:1) on shipped themes.
$ellipsis-border-mix
15%
Border tint on .pagination__ellipsis. Lower than $border-mix so the ellipsis reads as a passive separator. Set to 0 for a borderless ellipsis.
$ellipsis-fg-mix
50%
Foreground tint on the ellipsis glyph. Mixed against --kc-fg.
$hover-mix
8%
Hover-lift opacity over currentColor — theme-agnostic.
$nav-ghost
false
When false (default), .pagination__previous and .pagination__next paint with the same chrome as the numeric tiles. Set to true to drop the border and fill at rest (useful when embedded in another bordered surface).
$nav-padding-x
$size-normal
Horizontal padding on the nav slots. Larger than $padding-x so the multi-character label has breathing room against the chrome.
$chevrons
true
Emit decorative ‹ / › chevrons via ::before / ::after on the nav slots. CSS-only (two-border rotation), no font / SVG dependency.
$chevron-size
0.5em
Width and height of the chevron square (em-relative so it tracks the row font-size).
$chevron-thickness
0.125em
Stroke width.
$chevron-gap
$size-extra-small
Inline gap between the chevron and the label.
$current-combination
map.get($color-combinations, primary)
Bg/fg tuple for the active page. Falls back to $color-combination-default if a consumer's custom map omits primary.
$small-min-width
2rem
Min-width under .is-small.
$small-font-size
$size-small
Font-size under .is-small.
$large-min-width
3rem
Min-width under .is-large.
$large-font-size
$size-medium
Font-size under .is-large.
Override example
app.scss
@use '@adnap/krysalicss/module/pagination' with ( $gap: 0.75rem, $min-width: 2.75rem, $rounded-selector: '.is-pill',);
Active-page surface. Rebindable per instance to retint the current page without recompiling.
--kc-fg
Mixed at $border-mix for link borders and at 50% for the ellipsis glyph.
--kc-focus-ring
Painted on every link / prev / next on :focus-visible. Owned by helper/controls.
Accessibility
Wrap the strip in <nav aria-label="Pagination">.
Mark the active page with aria-current="page"; pair with
.is-current for static-site portability.
Disable prev/next via the native [disabled] attribute on
<button>, aria-disabled="true" on <a>, or .is-disabled. All
three route through the same disabled-control treatment.
Per WCAG 2.5.5, the per-link min-width is 2.5rem rather than the
AAA touch-target floor of 2.75rem: the row carries a gap between
every link, which satisfies the spacing exception. Removing the gap
warrants bumping $min-width to $global-min-touch-target.
Forced-colors mode pins borders to CanvasText and the active page
to Highlight / HighlightText so the state still reads on Windows
High Contrast.