#react#typescript#a11y

What Actually Moved Our Largest Contentful Paint

· 3 min read

Every codebase has one area everyone is a little afraid to touch. On our team, it was everything related to accessibility.

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

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.

When we finally measured, the numbers were worse than anyone guessed. Around 31% of the time spent on a typical change went into working around accessibility rather than building anything.

How it works

The fix turned out to be smaller than expected. Instead of adding another layer, we removed one and leaned on what Storybook already gives you out of the box.

Stripped of the project-specific bits, it looks like this:

.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:

  • Pair on the first few changes so the knowledge doesn't live in one head.
  • Delete dead code aggressively; it's the cheapest refactor there is.
  • Make the default the safe choice, not just the documented one.

Caveats

We still haven't solved bundle size. That's a post for another day, and honestly, I'm not sure we'll get it right the first time either.

There are cases where this falls apart. If your team is very small or your traffic is very spiky, the extra moving parts may not pay for themselves.

What's next

That's it for now. Next time I'll dig into form validation, which turned out to be closely related.

NA
Noah Achebe
Frontend engineer in San Diego. Writing about frontend engineering.