Skip to main content
VelinStyle v0.8.0
  1. Docs
  2. Getting Started
  3. Accessibility

Accessibility

VelinStyle is designed with accessibility in mind — WCAG 2.2 AA is structural, not optional. Components ship with ARIA, keyboard support, focus management, and utilities for screen readers, reduced motion, and forced colors. Enable enhanced contrast with data-velin-contrast="aaa" on <html>.

Visually Hidden (sr-only)

The .sr-only class hides an element visually while keeping it accessible to screen readers. Use .sr-only-focusable to reveal the element when it receives keyboard focus.

<!-- Hidden label for icon-only buttons -->
<button class="btn btn-icon" aria-label="Close">
  <velin-icon name="x" size="18"></velin-icon>
  <span class="sr-only">Close</span>
</button>

<!-- Skip link becomes visible on focus -->
<a href="#main-content" class="sr-only sr-only-focusable">
  Skip to main content
</a>

Tab into this area to reveal the skip link:

Skip to main content

Skip links let keyboard users jump directly to the main content, bypassing repeated navigation. VelinStyle includes a .velin-doc-skip class (used on this very docs site) that is hidden until focused.

<body>
  <a href="#main-content" class="skip-link">Skip to main content</a>

  <nav>...</nav>

  <main id="main-content">
    <!-- page content -->
  </main>
</body>

Focus Management

All interactive components display a visible focus ring. VelinStyle uses the :focus-visible pseudo-class so focus indicators only appear during keyboard navigation, not mouse clicks.

/* VelinStyle default focus ring */
:focus-visible {
  outline: 2px solid var(--velin-focus-ring-color, #6366f1);
  outline-offset: 2px;
}

/* Custom focus ring via utility */
.focus-ring-primary:focus-visible {
  --velin-focus-ring-color: var(--velin-primary);
}
.focus-ring-danger:focus-visible {
  --velin-focus-ring-color: var(--velin-danger);
}
Link button

Reduced Motion

VelinStyle respects the prefers-reduced-motion media query. When enabled, all animations and transitions are reduced to near-instant durations, ensuring users who are sensitive to motion have a comfortable experience.

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

You can also conditionally apply animations only when motion is allowed using the utility class .motion-safe:

<div class="animate-fade-in motion-safe">
  This fades in only when motion is allowed.
</div>

Forced Colors (High Contrast)

VelinStyle supports Windows High Contrast Mode and forced-colors: active. Component borders, focus rings, and interactive states are rendered using system colors so they remain visible in high-contrast themes.

@media (forced-colors: active) {
  .btn {
    border: 1px solid ButtonText;
  }
  .btn:focus-visible {
    outline: 2px solid Highlight;
  }
  .form-control {
    border-color: ButtonText;
  }
}

Focus not obscured (WCAG 2.4.11)

Fixed headers can hide focused elements when tabbing. VelinStyle sets scroll-padding-block-start from --velin-nav-height and provides .velin-scroll-pt-nav for custom layouts.

<html class="velin-scroll-pt-nav">…</html>

Target size (WCAG 2.5.8)

Primary controls meet 44×44px via target-size.css (.velin-target-touch).

Enhanced contrast (AAA, optional)

Set data-velin-contrast="aaa" on <html> for 7:1 token pairs. Verified with npm run test:contrast.

WCAG 2.2 checklist

CriterionVelinStyle
2.4.11 Focus Not Obscuredfocus-not-obscured.css
2.5.8 Target Sizetarget-size.css
2.1.1 KeyboardFocus trap, roving tabindex, WC updates in 0.7.0
1.4.6 Contrast (Enhanced)data-velin-contrast="aaa"

Testing in CI

npm run test:a11y (axe WCAG 2.2, 33+ pages) and npx velinstyle scan — see scanner rules.

Best Practices

Theme wählen