Why designing accessibly upfront is cheaper than fixing it after launch
A contrast error in a mockup can be fixed with a single click, the same error after launch costs person-days. This article shows how to check contrast, focus order, and touch target sizes during design, how accessibility acceptance criteria belong in the design handoff, and why designers share responsibility from the start.
Table of Contents
- 1. Why fixing accessibility after the fact costs more than designing first
- 2. Shift-left: thinking about accessibility from the wireframe stage
- 3. Checking contrast directly in the mockup
- 4. Annotating focus order in the design
- 5. Defining touch target sizes and spacing
- 6. Embedding accessibility acceptance criteria in the design handoff
- 7. Designers and developers: shared responsibility instead of silos
- 8. Accessible design systems and component libraries
- 9. Design-stage fixes vs. post-launch fixes compared
- 10. Summary
- 11. FAQ
1. Why fixing accessibility after the fact costs more than designing first
Software development has followed a well-known rule of thumb about defect costs for decades: a defect caught during the conception phase costs a fraction of the same defect caught after launch. The same logic applies to accessibility, yet it is routinely ignored in practice. A contrast problem that can be fixed in the mockup by switching to a different shade of grey turns, after development, into a search through dozens of templates, CSS files, and components where the color has been hardcoded. What costs five minutes in design often costs several person-days in code, because every occurrence has to be found, changed, and retested individually.
It gets even more expensive when structural problems only surface after launch, for example a missing focus order in a multi-step checkout or a form without proper semantic structure. Such defects can rarely be fixed with a CSS patch, they require reworking the HTML structure, retesting with screen readers, and often a full regression check of the affected flow. For Magento and Hyva stores in Germany, the Barrierefreiheitsstarkungsgesetz (BFSG) adds legal risk on top: rushed remediation because an auditor or a user reported a barrier is more expensive and more stressful than planned quality assurance during the design process.
2. Shift-left: thinking about accessibility from the wireframe stage
Shift-left originated in testing and describes moving quality assurance as early as possible in the development process instead of pushing it to the end. Applied to accessibility, that means asking, already at the first wireframe, in what order information makes sense for a screen reader user, rather than waiting until the HTML markup is written. Designers who think through heading hierarchy, landmark regions, and reading order at the sketch stage hand developers a blueprint that translates directly into semantic HTML instead of one that has to be reinterpreted afterward.
In practice, this means design tools like Figma let teams annotate frames with layer order, contrast values, and ARIA roles before a single developer is involved. Design tokens, the centrally maintained values for color, spacing, and typography, should be defined as contrast-safe from the start, so that every component consuming those tokens automatically stays WCAG-compliant. The following example shows a color token set exported as CSS custom properties, including a comment on the validated contrast ratio.
/* Design tokens exported from Figma variables */
/* Each color pair is pre-validated against its intended background */
:root {
/* Text on white background, contrast ratio 7.2:1 (AAA) */
--color-text-primary: #27272a;
/* Secondary text on white background, contrast ratio 4.6:1 (AA) */
--color-text-secondary: #52525b;
/* Placeholder text, informational only, not required to meet 4.5:1 */
--color-text-placeholder: #a1a1aa;
/* Primary button background, white text on top, contrast ratio 8.1:1 */
--color-button-primary-bg: #18181b;
--color-button-primary-text: #ffffff;
/* Error state, text on white background, contrast ratio 5.9:1 */
--color-error: #b91c1c;
}
/* Component consuming the tokens automatically stays WCAG-compliant */
.form-label {
color: var(--color-text-primary);
}
.form-hint {
color: var(--color-text-secondary);
}
3. Checking contrast directly in the mockup
Color contrast is the accessibility aspect easiest to check during design, and at the same time one of the most common violations in live stores. WCAG 2.2 requires a contrast ratio of at least 4.5:1 against the background for normal text at Level AA, and at least 3:1 for large text starting at 18pt or 14pt bold. Plugins like Stark, Able, or the built-in contrast tools of modern design applications calculate this ratio directly in the mockup, while the color is still easy to change, not after it has been built into thirty templates.
For design systems, it is also worth running an automated check across the entire color palette so that new color combinations do not accidentally drop below the threshold. The calculation is based on the relative luminance of both colors according to the WCAG formula. A small script that runs this check as part of the design token pipeline prevents a new grey tone for secondary text from silently falling below 4.5:1 long before a developer ever copies the color into code.
// Contrast validation script, run against design tokens before export
// Implements the WCAG relative luminance formula
function relativeLuminance(hex) {
const [r, g, b] = hexToRgb(hex).map((channel) => {
const c = channel / 255;
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
});
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
function contrastRatio(hexForeground, hexBackground) {
const l1 = relativeLuminance(hexForeground);
const l2 = relativeLuminance(hexBackground);
const lighter = Math.max(l1, l2);
const darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
function hexToRgb(hex) {
const value = hex.replace('#', '');
return [0, 2, 4].map((i) => parseInt(value.substring(i, i + 2), 16));
}
const tokens = {
textSecondary: '#52525b',
background: '#ffffff',
};
const ratio = contrastRatio(tokens.textSecondary, tokens.background);
if (ratio < 4.5) {
throw new Error(`Token textSecondary fails AA: ${ratio.toFixed(2)}:1`);
}
console.log(`textSecondary passes AA: ${ratio.toFixed(2)}:1`);
4. Annotating focus order in the design
The visual order in a mockup does not automatically match the order a keyboard user experiences while tabbing through, especially in multi-column layouts, card grids, or forms with fields arranged side by side. Without an explicit annotation, the developer decides the focus order at their own discretion, often simply following the order elements land in the source code, which does not necessarily match the reading order the design intended. A numbered overlay annotation directly on the frame, showing the intended tab order, removes this ambiguity entirely.
This annotation matters most for modals, multi-step forms, and custom components like date pickers or comboboxes, where the DOM order can diverge significantly from the visual arrangement. Developers should resolve the order primarily through DOM source order, not through positive tabindex values, which are hard to maintain and easily create inconsistencies. The following example shows how a focus order numbered in the design is translated into natural DOM order, with comments referencing the corresponding design annotation.
<!-- Focus order annotated in the design frame as 1-5, mapped here via DOM source order -->
<!-- WRONG: relying on positive tabindex to force an order -->
<div class="checkout-summary">
<input type="text" name="promo-code" tabindex="3">
<button type="submit" tabindex="1">Complete order</button>
<a href="/cart" tabindex="2">Back to cart</a>
</div>
<!-- RIGHT: source order matches the intended focus order from the design annotation -->
<div class="checkout-summary">
<!-- design annotation #1 -->
<a href="/cart" class="checkout-summary__back">Back to cart</a>
<!-- design annotation #2 -->
<label for="promo-code">Promo code</label>
<input type="text" id="promo-code" name="promo-code">
<!-- design annotation #3 -->
<button type="submit">Complete order</button>
</div>
5. Defining touch target sizes and spacing
WCAG 2.2 introduced Success Criterion 2.5.8 "Target Size (Minimum)" at Level AA, requiring a minimum size of 24 by 24 CSS pixels for interactive elements, with defined exceptions for cases such as inline links in body text or when an equivalent, larger target is available elsewhere. The stricter Success Criterion 2.5.5 "Target Size (Enhanced)" at Level AAA recommends 44 by 44 pixels. If these dimensions are not defined as a minimum in the design system for buttons, icons, and interactive cards, every developer ends up deciding individually how large a clickable area should be, with correspondingly inconsistent results.
In practice, this affects compact UI elements in particular, such as icon buttons in filter bars, pagination arrows, or close icons in modals, which look large enough in the desktop mockup but drop below the minimum size in the mobile view when breakpoints are not checked separately. Beyond raw target size, the spacing between adjacent touch targets is critical to avoid accidental taps on the wrong element. A design system should therefore define both minimum sizes and minimum spacing as reusable spacing tokens.
/* Touch target tokens, enforced across every interactive component */
:root {
--target-size-min: 24px; /* WCAG 2.5.8 Level AA minimum */
--target-size-comfort: 44px; /* WCAG 2.5.5 Level AAA recommended */
--target-spacing-min: 8px; /* minimum gap between adjacent targets */
}
/* Icon button, visually 20px icon, but the tappable area meets the minimum */
.icon-button {
min-width: var(--target-size-comfort);
min-height: var(--target-size-comfort);
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
}
.icon-button svg {
width: 20px;
height: 20px;
}
/* Pagination links spaced to avoid accidental adjacent taps */
.pagination__item + .pagination__item {
margin-left: var(--target-spacing-min);
}
6. Embedding accessibility acceptance criteria in the design handoff
A design handoff that contains only visual specifications like colors, spacing, and typography leaves every question about keyboard operation, screen reader behavior, and ARIA structure open, and those questions then get decided implicitly by the developer, usually under time pressure and without checking back with design. Accessibility acceptance criteria are explicit, testable requirements attached to every ticket in the handoff alongside the visual specification: expected keyboard behavior, visible focus indicators, screen reader announcement text for dynamic status changes, and the expected semantics, for example whether an element should be marked up as a button or as a link.
The effect on the definition of done is significant: a ticket no longer counts as finished once it "looks right", but only once the documented accessibility criteria are demonstrably met. This also moves test cases earlier in the process, because QA and development already know the criteria before the first line of code is written, instead of improvising them at the end of the sprint. The following example shows a JSON template for a handoff ticket with explicit accessibility acceptance criteria.
{
"ticket": "PDP-482",
"component": "Product image gallery with thumbnails",
"visualSpec": {
"figmaFrame": "PDP / Gallery / v3",
"breakpoints": ["mobile", "tablet", "desktop"]
},
"accessibilityAcceptanceCriteria": [
"Thumbnails are navigable via arrow keys once one has focus",
"Active thumbnail has aria-current='true' and a visible focus ring",
"Main image change is announced via aria-live='polite': 'Image 2 of 6'",
"Every thumbnail has an alt attribute with product detail, not just 'Image 2'",
"Touch target of every thumbnail is at least 44 by 44 CSS pixels",
"Contrast ratio of the active border is at least 3:1 against the background"
],
"testMethod": "Keyboard test + NVDA/VoiceOver + automated axe-core",
"status": "ready-for-development"
}
7. Designers and developers: shared responsibility instead of silos
A common organizational pattern treats accessibility as a purely developer-owned task checked off by QA at the end of the sprint. This pattern overlooks that many barriers originate in design and can be avoided there with far less effort than in code. Designers need a basic understanding of WCAG principles for this, not at a developer's depth, but enough to judge contrast, focus order, and target sizes independently before a mockup reaches the development process.
In practice, this can be anchored through fixed rituals: an accessibility check as a fixed part of every design review before development starts, joint pairing sessions where designers and developers try out a screen reader together, and a shared checklist that belongs not only to QA but is maintained by both roles. A named accessibility champion per team, who does not have to be a developer, keeps the topic visible and prevents responsibility from diffusing between design and development.
8. Accessible design systems and component libraries
The biggest lever for accessibility in the design process is the component library itself. Once accessibility is solved correctly once in the base component of a button, form field, or modal within the design system, including contrast, focus state, and expected ARIA semantics, every single use of that component benefits automatically, without every team having to repeat the same check. Conversely, a single defect in the base component multiplies across every place it is used, which is exactly why extra care at this level pays off disproportionately.
To keep the design system and the code components from drifting apart, every Figma component should be linked to the corresponding Hyva or Alpine.js pattern in shared documentation, for example through Storybook or an internal pattern library. Changes to the design component then trigger a check on whether the corresponding code component is still in sync. A short accessibility checklist per component, right in the documentation, makes the requirements traceable for every team instead of hiding them in a separate, rarely-read WCAG document.
9. Design-stage fixes vs. post-launch fixes compared
The following overview compares typical accessibility tasks, once solved during the design stage and once fixed after launch. The difference in effort makes clear why investing in early checks pays off.
| Task | Fix during the design stage | Fix after launch | Effort difference |
|---|---|---|---|
| Contrast check | Adjust color token in the mockup, minutes | Find and replace the color across every template and CSS file | Significantly higher |
| Focus order | Add an overlay annotation to the frame | Rework the HTML structure of multiple templates and retest | Significantly higher |
| Touch target size | Adjust a spacing token in the design system | Fix each affected component individually in code | Significantly higher |
| ARIA semantics for custom widget | Document the expected role in the handoff | Restructure existing markup after the fact | Significantly higher |
| Legal risk (BFSG) | No risk, checked before launch | Possible complaint, rushed remediation under time pressure | High, including reputational risk |
In all five cases, the difference is not about how technically difficult the solution itself is, but about when it enters the process. Changing a wrongly chosen color in a mockup costs one click, finding and replacing the same color across fifty shipped templates costs days and carries extra regression risk.
Mironsoft
Accessibility, design systems, and accessibility implementation for Magento and Hyva stores
Ready to embed accessibility into design the right way?
We audit your design system for contrast, focus order, and touch target sizes, build accessibility acceptance criteria into your handoff process, and bring design and development into one shared accessibility workflow.
Design system audit
Check contrast, focus states, and touch targets in existing components
Handoff process
Embed accessibility acceptance criteria into tickets and definition of done
Team workshops
WCAG fundamentals for designers, establishing joint reviews with development
10. Summary
Embedding accessibility in the design process is not a luxury, it is the economically sound order in which accessibility work should happen. A contrast error costs one click in the mockup, often days in code. Focus order can be fixed with a numbered annotation on the frame instead of being rescued later with tabindex hacks in the markup. Touch target sizes of at least 24 by 24, ideally 44 by 44 CSS pixels, belong in the design system as spacing tokens, not left to the individual judgment of each developer.
Accessibility acceptance criteria in the design handoff turn implicit assumptions into explicit, testable requirements and move test cases to the beginning of the process. The biggest lever lies in the component library: solved correctly once, every use benefits automatically. In the end, what is needed is shared responsibility between design and development, not a silo structure in which accessibility shows up only at the end of the sprint as rework.
Embedding Accessibility in the Design Process, the key points at a glance
Cost advantage
A fix in the mockup costs minutes, the same fix after launch costs person-days across dozens of templates.
Design-stage checks
Check contrast, focus order, and touch target sizes in the mockup with tooling before code is written.
Acceptance criteria
Explicit, testable accessibility requirements in the handoff ticket instead of implicit assumptions by development.
Shared responsibility
Designers and developers check together, accessibility is not a pure QA task at the end of the sprint.