improving accessibility in my blog using axe-core tests

November 9, 2025

I have been using axe-coreaxe-coreAn automated accessibility testing engine maintained by Deque. for automated accessibility testing for various personal projects, and recently I added it to this site. This helped me discover that the colours I was using in my code blocks had insufficient colour contrast, making them hard to read for users with colour vision deficiencies.

Why accessibility matters

I think that all users should have equal access to content on the web, and that spending developer time to remove barriers to access is worthwhile.

Using axe-core

I added automated accessibility checks with @axe-core/playwright so every commit can catch regressions early.

1. Select rules

In tests/accessibility.spec.ts I defined the rule sets I wanted to enforce:

const tags = [
	'wcag2aa',
	'best-practice',
];

2. Reusable helper for tests

async function analyzeAccessibility(page: Page, url: string) {
	await page.goto(url, { waitUntil: 'networkidle' });
	await page.waitForTimeout(200); // allow late font/CSS swaps

	const results = await new AxeBuilder({ page })
		.withTags(tags)
		.analyze();

	if (results.violations.length) {
		throw new Error(`A11y violations on ${url}: ${JSON.stringify(results.violations, null, 2)}`);
	}
}

This helper function navigates to a given URL, waits for the page to load, runs Axe accessibility analysis on the page using the specified tags, and throws an error with detailed info if any accessibility violations are found.

test('all blog posts', async ({ page, baseURL }) => {
	const posts = getBlogPosts();

	for (const post of posts) {
		const url = `${baseURL!}/blog/${post.slug}`;
		console.log(`Analyzing accessibility for blog post: ${url}`);
		await analyzeAccessibility(page, url);
	}
});

This test iterates over all blog posts and uses the analyzeAccessibility helper to check each post for accessibility issues.

3. Improve code block contrast

Initial code blocks failed enhanced contrast checks. I now use Shiki for highlighting and ensure sufficient contrast with a small CSS tweak in app/global.css:

pre.shiki {
	overflow-x: auto;
	line-height: 1.55;
	border-radius: 0.5rem;
	padding: 0.75rem 0.9rem;
	background-color: #0d1117;
	color: #e6edf3;
	border: 1px solid #30363d;
}

Conclusion

Adding automated accessibility tests with axe-core has helped me catch and fix accessibility issues. I also integrated these tests into my CI pipeline to ensure accessibility is baked-in as part of the development process. It is worth remembering that automated tests can only catch a subset of accessibility issues, so manual tests of keyboard navigation and screen reader usage, as well as user feedback, are also important components of building an accessible site.