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.

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 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:
<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.
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.
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 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.
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.
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.
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 (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:
npx sv add paraglideOnce 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.
Key takeaways:
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.