Accessibility

Accessibility isn't something we bolt on before launch. We build it in from the first commit, because a site that doesn't work for everyone isn't really finished.

Part of our published engineering standards: Performance, Accessibility, Security, Best Practices, and SEO.

Semantic HTML first

Every page starts with meaningful markup. We use native HTML elements for what they're actually for: <nav> for navigation, <main> for the primary content, <article> for self-contained pieces, and <details>/<summary> for things like our FAQ accordions, which run without a line of JavaScript.

Why semantic HTML matters Show less

Screen readers, search engines, and assistive tech all lean on semantic structure to make sense of your content. A <div> with a click handler isn't a button: it never lands in the keyboard tab order, never announces its role, and ignores Enter and Space. So we use actual <button> elements, a proper heading hierarchy, and real landmark regions, and every user finds their way around the same way.

Headings run in order, h1 through h6, and every section heading carries a deep-linkable anchor ID. Screen reader users can jump around by heading, and everyone else gets a shareable link straight to a section.

Keyboard navigation

Every interactive element works with the keyboard alone. No mouse required.

How we handle keyboard access Show less

Our skip link lets keyboard users jump straight to the main content instead of tabbing through the whole nav first. It stays hidden until it's focused, then shows up with a high-contrast outline you can't miss.

Navigation dropdowns take full arrow-key control: Up and Down move between links, Home and End jump to the first and last, Escape closes the menu, and Tab moves focus out the way you'd expect. The focus ringThe visible ring that appears around interactive elements when navigating by keyboard uses :focus-visible everywhere, a 2px outline with a 2px offset, so keyboard focus is always visible but never clutters things for mouse users.

Respecting motion preferences

Animation adds warmth and polish, but it can make people with vestibular disorders feel ill. So we honour the prefers-reduced-motion media query on every animation we ship.

What we disable and how Show less

When someone's OS is set to reduce motion, we switch off the scroll-reveal animations (fade-up, scale-in, the staggered cascades), the hover micro-interactions, and the CTA rainbow. Everything stays fully visible. Nothing hides behind an animation that never plays.

We do it in two layers. A global kill-switch in our CSS reset drops animation-duration and transition-duration to near zero for everything, and individual animation files add their own prefers-reduced-motion overrides where we want finer control. The Sparkles component goes further, with its own IntersectionObserver motion check that stops spawning particles altogether when reduced motion is on.

Windows high contrast & forced colors

When forced-colors modeA Windows accessibility feature that overrides all colours to improve visibility for users with low vision is on, the browser overrides every colour on the page. If you don't handle that deliberately, custom borders, focus rings, and decorative bits can vanish and take the site's usability with them.

Our forced-colors strategy Show less

We ship a dedicated @media (forced-colors: active) block that puts visible borders back on buttons (so they don't disappear into the background), keeps focus indicators distinct, and holds card edges in place. That covers 90%+ of browsers, meaning every Chromium browser plus Firefox on Windows.

Instead of fighting the user's chosen colour scheme, we work with it. We use transparent borders that show up when the browser swaps in system colours, and we make sure controls stay recognisable by shape and border, not by colour alone.

Touch target sizing

Every interactive element meets the WCAG 2.5.5 (AAA) enhanced touch-target size of 44 × 44 pixels, well past the 24×24px WCAG 2.5.8 (AA) minimum, even when the element looks smaller than that.

How we achieve this without visual bloat Show less

Take our heading anchor links. The "#" icon looks small, but a ::after pseudo-element stretches the clickable area to a full 44px. Someone with a motor impairment, or anyone on a touchscreen, can tap it without aiming carefully, and the design still looks clean.

Same goes for navigation links, buttons, toggle switches, and the FAQ accordions. If it's interactive, you can tap it, on any device, at any size.

Accessible view transitions

Our sites use Astro's view transitionsClient-side page transitions that swap content without full reloads, providing app-like navigation for smooth page-to-page navigation. Client-side routing can quietly break accessibility, though, if you don't manage focus carefully.

How we preserve focus after navigation Show less

After every swap we move focus to #main with preventScroll: true, so keyboard users land in the new page's content instead of being stranded at the top of the DOM. It behaves like a normal full page load, but keeps the fluid feel of client-side navigation.

Accessibility is the baseline

Every TechTailors site ships this way by default.

Start a Conversation