I Audited My Own Portfolio for WCAG 2.2 — Here's What I Found in 30 Minutes
Meta: I audited my portfolio for WCAG 2.2 and found six critical accessibility issues I'd been ignoring. Here's how to find them in yours.
Keyword: WCAG 2.2 audit checklist developer
Tags: #accessibility #webdev #wcag #frontend
The Moment I Realized I Was Part of the Problem
Last week, I was reviewing accessibility best practices for a client project when it hit me: I haven't formally audited my own portfolio in years. You know, the one I show to potential clients when I talk about how much I care about inclusive design.
Oof.
So I decided to do something radical—actually practice what I preach. I set a timer for 30 minutes, grabbed a couple of free tools, and started poking around. What I found was both humbling and, frankly, pretty typical. And that's exactly why I'm writing this.
The web is broken for accessibility. The WebAIM Million 2025 report shows that 95.9% of websites fail basic WCAG checks. Ninety-five point nine percent. That's not bad luck. That's us. Developers. We did this. Usually without meaning to, usually while thinking about 47 other things, but we did it.
Here's the good news: we can also fix it. And if the EU's Accessibility Act (EAA) being enforced as of June 2025 isn't motivation enough, maybe knowing that your actual users—whether they're blind, colorblind, using only a keyboard, or just on a tiny mobile screen in bad sunlight—will actually be able to use your site, is.
Let me walk you through what I found, how I found it, and how to fix it.
The Tools (All Free, All Good)
Before we dig in, let me be clear: you don't need expensive software.
axe DevTools (browser extension, free) — This is my workhorse. It runs automated accessibility scans and flags issues with severity and WCAG criteria. Chrome, Firefox, Edge. Get it.
WAVE (browser extension, free) — Shows you a visual representation of content structure, labels, and warnings. Slightly different angle than axe, so both are worth running.
Chrome DevTools — Accessibility Tree (built in, free) — Under DevTools → Elements → Accessibility, you can see how your page is parsed by assistive technology. This is eye-opening.
Keyboard testing (your keyboard, free) — Press Tab. See what happens. Try to navigate your entire page without touching the mouse. This matters more than any tool.
That's it. Ten minutes to set up. Let's go.
What I Found: Six Things That Made Me Wince
1. Missing and Terrible Alt Text on Images
The issue: I had a gorgeous hero image on my portfolio landing page. Beautiful. Completely undescribed.
<!-- ❌ What I had -->
<img src="portfolio-hero.jpg" />
<!-- ✅ What I should have -->
<img
src="portfolio-hero.jpg"
alt="Portfolio website displaying three web design projects with dark theme and gradient accents"
/>
What it means for real users: Blind users get nothing. Screen readers say "image" and move on. Image broken or slow to load? Sighted users see the broken image icon. Blind users see nothing—they don't even know there was supposed to be content there.
The fix: Write alt text that describes the content and purpose of the image. Not poetic. Not alt="beautiful sunset". Useful. What does this image do on your page? If it's decorative, use alt="".
2. Insufficient Color Contrast (The Sneaky One)
My design had a really slick dark gray text on a slightly darker gray background. Very trendy. Very unreadable if you have low vision, color blindness, or are just squinting at your phone in daylight.
axe flagged it: 3.2:1 contrast ratio. WCAG AA requires 4.5:1 for normal text, 3:1 for large text (18px+ or 14px bold+).
/* ❌ What I had (3.2:1 - FAIL) */
.post-date {
color: #666666;
background: #1a1a1a;
font-size: 14px;
}
/* ✅ What I fixed (4.8:1 - PASS) */
.post-date {
color: #cccccc;
background: #1a1a1a;
font-size: 14px;
}
Quick way to check: Use the WebAIM contrast checker (free, no login). Paste your hex codes, see your ratio. Aim for 4.5:1 unless your text is genuinely big.
3. Focus Indicators (The Invisible Tab)
I had removed the default browser focus outline on links because it "looked ugly." Instead, I'd added a subtle :hover effect. Very pretty. Very broken if you only use keyboard.
Someone using a keyboard to navigate my site would Tab onto a link and... see nothing change visually. Where am I? Did that work? Panic.
/* ❌ What I had */
a {
outline: none; /* THE SIN */
}
a:hover {
color: #0066ff;
}
/* ✅ What I fixed */
a:focus-visible {
outline: 3px solid #0066ff;
outline-offset: 2px;
}
a:hover {
color: #0066ff;
}
The rule: Never remove the default focus outline without replacing it. :focus-visible is your friend—it shows the outline when using keyboard, but not when clicking with a mouse. Best of both worlds.
4. Unlabelled Form Inputs (The Invisible Ask)
I have a contact form. The form had inputs, but they were only labeled visually—the HTML had no <label> elements.
<!-- ❌ What I had -->
<input type="email" placeholder="Your email" />
<!-- ✅ What I should have -->
<label for="contact-email">Email address</label>
<input type="email" id="contact-email" placeholder="Your email" />
Why this matters: A screen reader user reaches the input field and hears... nothing. They don't know what the field is for. The placeholder disappears when they type. Without a label, they're flying blind.
Even better: If you want to visually hide the label (for design reasons), use CSS:
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
<label for="contact-email" class="sr-only">Email address</label>
<input type="email" id="contact-email" placeholder="Your email" />
The label is there for assistive tech. The visual design is unchanged.
5. Keyboard Navigation Trap in My Project Modal
I have a modal that displays project details. You Tab through the form, but when you reach the last button, Tab wraps back to the first button inside the modal—you can't escape without clicking outside or pressing Escape.
This is called focus trap without escape, and it's particularly bad if you're keyboard-only.
// ✅ Simple fix: Handle Tab in the last focusable element
const lastButton = document.querySelector('.modal .btn-close');
lastButton.addEventListener('keydown', (e) => {
if (e.key === 'Tab' && !e.shiftKey) {
e.preventDefault();
document.querySelector('.modal .btn-primary').focus();
}
});
// OR, better: Use a proper focus trap library behavior
// But here's the core idea—don't trap users in a modal without a clear exit.
Real talk: The best fix is making sure your modal can be closed with Escape (which browsers often handle automatically), and that focus moves back to the trigger element when the modal closes.
6. No Skip Navigation Link
This is the one that made me laugh at myself. I preach about skip links, and mine had zero.
A skip link is a link at the very start of your HTML that says "Skip to main content." It's hidden by default, but visible when you Tab to it. For keyboard-only users, this saves them from Tabbing through your entire navigation menu every single page.
<a href="#main-content" class="skip-link">Skip to main content</a>
<nav>
<!-- navigation stuff -->
</nav>
<main id="main-content">
<!-- your actual content -->
</main>
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: white;
padding: 8px;
text-decoration: none;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
When you Tab onto it, it slides into view. Click it, and you jump straight to #main-content. Keyboard users say a silent thank you.
WCAG 2.2: What's New and What I Hit
WCAG 2.2 added 9 new criteria in October 2023. I triggered at least two:
Focus Appearance (2.4.13) — That focus indicator I removed? That's criterion 2.4.13. WCAG now demands a visible focus indicator with at least 3:1 contrast against adjacent colors.
Target Size (2.5.8) — Interactive elements should be at least 24px × 24px (or 24px of spacing between them). My social media icons in the footer were 16px. Easy miss. Easy fix.
Both are WCAG AA level. Both are things I didn't know about when I started, but both are important because they make the web usable for more people.
Your Quick-Start Checklist: 10 Minutes
If you only read this far, here's what to do right now:
- Install axe DevTools, open your site, run the scan. Note the failures.
-
Check all images. Does each
<img>have useful alt text? (Notalt="image", actual description.) - Test with Tab only. Close your trackpad. Can you navigate your entire site with Tab and Enter? Is focus always visible?
-
Check form labels. Every input should have a
<label>with a matchingforattribute. - Test color contrast. Pick your key text colors. Run them through WebAIM's contrast checker. Aim for 4.5:1.
That's it. Thirty minutes, max.
The Thing About Being a Developer Who Cares
I think we fail accessibility not because we're careless, but because the defaults are broken. The web platform doesn't make inclusive design automatic. You have to opt in.
But once you see it—once you understand that real humans depend on this stuff—it becomes harder to ignore. And the good news is that it's not hard. It's just... intentional.
I fixed my six issues in an afternoon. My portfolio loads faster, is more usable for everyone, and I can talk to clients with actual credibility now.
You can too.
Priya Nair is a frontend developer based in Amsterdam. She writes about accessibility, inclusive design, and the occasional CSS rabbit hole. When she's not auditing her own code, you'll find her advocating for the web that works for everyone.
Top comments (0)