The Accessibility Bugs Our Test Suite Never Caught
There is no shortage of articles about Svelte. Most of them cover the happy path. This one is about what happened after the happy path ended.
We had good intentions. We even had a document describing how accessibility should work. The trouble was that the document and the code had quietly gone their separate ways.
What was going wrong
The setup was ordinary: Svelte at the edges, Vue doing most of the heavy lifting, and a handful of scripts nobody wanted to own. It worked well until usage roughly doubled over a single quarter.
Most of the complexity was accidental. Over the years we'd layered three different approaches to accessibility on top of each other, and each one made sense at the time.
The fix
Rather than a big-bang rewrite, we migrated one module at a time over about 5 weeks, keeping both paths alive behind a flag.
Here's a trimmed-down version of what we ended up with:
.card-list {
container-type: inline-size;
}
@container (min-width: 36rem) {
.card {
display: grid;
grid-template-columns: 12rem 1fr;
gap: 1.5rem;
}
}
This alone let us delete a surprising amount of code elsewhere in the project.
A few things that helped along the way:
- Write the migration guide before writing the migration.
- Keep the old path around until the new one has survived a real incident.
- Agree on what "done" means before the first pull request.
- Pair on the first few changes so the knowledge doesn't live in one head.
Trade-offs
None of this is free. The new approach is a bit more verbose, and newcomers occasionally ask why we don't just use Vite for everything. That's a fair question with a boring answer: we tried, and it made accessibility harder to reason about.
We still haven't solved server-side rendering. That's a post for another day, and honestly, I'm not sure we'll get it right the first time either.
Closing thoughts
Six months in, nobody on the team wants to go back. That's about the best review a change like this can get.