Learn Svelte - Accessibility & UX
Series/Learn Svelte/Episode 17
Episode 17 of 24

Learn Svelte - Accessibility & UX

This episode covers experiences that everyone can use: ARIA roles and keyboard navigation, semantic HTML and accessible components, responsive design and progressive enhancement, and the basics of internationalization and localization.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

A good app is used by everyone — including those who navigate with a keyboard, screen reader, or a slow device. Accessibility isn't an add-on feature; it's a measure of software quality.

This episode covers ARIA roles and keyboard navigation, semantic HTML and accessible components, responsive design and progressive enhancement, and the basics of internationalization and localization.

When you're done, you can build interfaces that don't exclude anyone. Proper accessibility also brings a pleasant side effect: cleaner markup and better SEO.

The success metric for this episode is simple: an app that can be used entirely with a keyboard. A quick way to check it — navigate the whole page with Tab, Enter, and Esc without touching the mouse.

ARIA Roles and Keyboard Navigation

ARIA Roles as a Supplement

ARIA tells assistive technology the role of an element that isn't available in HTML. Its first rule: use a semantic element when one exists. ARIA roles only supplement, never replace, the meaning of HTML.

When an element needs a role that HTML can't convey, use ARIA sparingly and precisely. Too many wrong ARIA roles are worse than none at all.

For custom components, make sure the keyboard behavior is complete and the role is clear:

Keyboard-accessible button
<script>
  let { label, onklik } = $props()
</script>
 
<button type="button" aria-label={label} onclick={onklik}>
  Kirim
</button>

aria-label={label} provides a name that assistive technology reads when the visual text isn't descriptive. A native <button> element already comes with keyboard navigation and screen reader support for free.

Visible and Ordered Focus

Keyboard navigation depends on clear focus. Don't remove the browser's default outline without providing a replacement. Focus order follows DOM order — arrange the DOM to match the visual order instead of reversing it with CSS.

Use :focus-visible to show an outline only during keyboard navigation, not mouse clicks. This technique keeps the design clean while preserving guidance for keyboard users.

Semantic HTML and Accessible Components

Elements That Convey Meaning

Screen readers interpret a page through its HTML structure. Use <header>, <nav>, <main>, and <footer> instead of stacked <div>s. Headings <h1> through <h6> should follow a correct hierarchy without skipping.

Forms are the most tested area. Connected labels make screen readers announce a field's name correctly:

Label connected to an input
<label for="email">Alamat email</label>
<input
  id="email"
  name="email"
  type="email"
  autocomplete="email"
  required
/>

for="email" and id="email" connect the label to the input. autocomplete="email" lets the browser fill values automatically — convenient and typo-reducing.

A common label mistake: putting text in aria-label while the visible text differs. Both must align, because screen readers announce the ARIA label, not the visible text.

Honest Interactive Elements

Buttons should be <button>, not <div>s with a click handler. Links should be <a href>, not other elements pretending to be one. Native browser interactive elements provide keyboard navigation, focus, and screen reader support for free.

Responsive Design and Progressive Enhancement

Mobile-first and Fluid Layouts

Start from the smallest screen size, then improve toward large screens. Use responsive units like clamp() for typography and grid for layout. Testing on real screen widths is more useful than just resizing a window.

Also mind large enough touch targets — at least 44 pixels for interactive elements — and spacing that prevents accidental taps.

Progressive Enhancement

Build a functional core that works without JavaScript, then enhance it. Pure HTML forms can still submit data even if scripts fail to load. Hydration then adds interactivity on top of a working foundation — an approach that also improves load times on slow networks.

Apply the same principle to media: provide alt text for images and transcripts for video, so content stays available when media fails to load.

Internationalization and Localization

Separating Text from Code

Internationalization (i18n) prepares an app for many languages; localization (l10n) translates its content. The first step is not writing text directly in components. Tools like Paraglide SvelteKit simplify the process:

Add i18n to the project
npx sv add paraglide

Once added, you store messages in a per-language format and call them with auto-generated functions. The system also handles language selection based on URL or browser preferences.

Translation isn't the only thing that changes between languages: date formats, numbers, and text direction need attention too. A good i18n library helps handle these.

Conclusion

Key takeaways:

  • Use semantic HTML before adding ARIA roles.
  • Maintain visible focus and a logical navigation order.
  • Connect labels to inputs for accessible forms.
  • Don't remove focus outlines without a replacement.
  • Build mobile-first with progressive enhancement.
  • Separate text from code so the app is ready to translate.

Next, in episode 18 you'll learn architecture & design patterns — feature-based project structure, reusable component libraries and composables, separating logic, UI, and data, and scalable Svelte architecture. The accessibility you've built stays intact with a clean architectural pattern.

Learn Svelte - Accessibility & UX | Learn Svelte