Building websites that work for everyone, not just a fraction of visitors
Building a website isn't just about what looks good on your monitor. It's about who can actually use it. Accessibility isn't an optional add-on for a "later" sprint. It's foundational. Whether you're coding a personal portfolio like rguidry.dev or scaling an enterprise platform, the Web Content Accessibility Guidelines (WCAG) lay out the roadmap for sites that everyoneânot just a fraction of visitorsâcan navigate and use.
I learned this lesson the hard way when I launched my site's first version. The design looked sleek on my 27-inch monitor, but when I ran an audit with Lighthouse, the accessibility score was embarrassingly low. Missing <main>
tags, unlabeled navigation, poor contrast ratios. It wasn't just that a screen reader user would struggleâit also meant search engines weren't parsing my content effectively. Accessibility and SEO are more tightly bound than most developers realize.
Before diving into the checklist of accessibility issues, it's worth making the SEO link explicit. Search engines crawl sites in ways that parallel how assistive technologies parse content. Clean, semantic HTML, labeled navigation, alt textâall these are signals for both accessibility and discoverability.
<main>
or <section>
tags, crawlers can't distinguish priority content. Users with screen readers face the same confusion.When I patched up my first build of rguidry.dev, I saw two improvements: accessibility audits went green, and pages indexed faster. Accessibility wasn't charityâit was strategy.
At the core of WCAG compliance is semantic HTML. Think of it as the skeleton of your site. Without it, both humans and machines lose context.
<main>
tag: The main content needs to be explicitly wrapped. Without it, screen readers can't jump directly to the primary content, and crawlers can't weigh what's essential.<nav>
tags: Wrapping navigation links inside <nav>
blocks makes site structure obvious. This matters for both accessibility tree parsing and search engines organizing links.<section>
tags: Proper <section>
elements give meaning to grouped content. That improves heading hierarchy and search indexing.When I first audited rguidry.dev, everything was just <div>
. Functionally fine, but invisible to anyone using assistive tech. It also made my analytics confusing: users were bouncing faster because they couldn't find what they needed.
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Portfolio</title>
</head>
<body>
<header>
<h1>RGuidry.dev</h1>
</header>
<nav aria-label="Main navigation">
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li><a href="/projects">Projects</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
<main>
<section>
<h2>About Me</h2>
<p>Developer, builder, problem-solver...</p>
</section>
</main>
<footer>
<p>© 2025 rguidry.dev</p>
</footer>
</body>
</html>
Semantic HTML solves a lot, but ARIA fills the gaps. Accessible Rich Internet Applications (ARIA) attributes describe roles, states, and properties where HTML falls short.
aria-label
for navigation: Without labels, multiple nav menus are indistinguishable. Adding aria-label="Primary navigation"
gives clarity.aria-current
for active states: A simple aria-current="page"
tells users (and bots) where they are in the site.role
attributes: Interactive elements like custom buttons need explicit roles, or they'll be invisible to assistive tech.When I added ARIA to my mobile menu toggle on rguidry.dev, the difference was instant. VoiceOver could finally announce "Menu button, collapsed" instead of "button." That precision is the line between usable and confusing.
<nav aria-label="Primary navigation">
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li><a href="/projects">Projects</a></li>
<li><a href="/contact">Contact</a></ul>
</nav>
<button
aria-label="Open mobile menu"
aria-controls="mobile-menu"
aria-expanded="false"
role="button">
â°
</button>
Forms are often the biggest accessibility pitfall. Without descriptive labels, users are left guessing.
aria-describedby
for inputs: This attribute ties helper text to inputs, clarifying requirements like "Password must be 8 characters."aria-expanded
for mobile menu toggle: Screen readers need to know whether content is expanded or collapsed.aria-controls
: This attribute links a button to the content it toggles, essential for understanding dynamic menus.On my contact form, I initially relied on placeholders as labels. A common mistake. Once a user started typing, the placeholder disappeared, leaving no accessible label. Switching to <label>
tags with for attributes fixed it immediately.
<form>
<label for="email">Email address</label>
<input
type="email"
id="email"
name="email"
aria-describedby="emailHelp">
<small id="emailHelp">We'll never share your email.</small>
<button type="submit">Submit</button>
</form>
Alt text is the most obvious accessibility issue, but it's often mishandled.
alt
attributes: Every image must have an alt attribute. Decorative images should use alt=""
.aria-label
for complex images: Graphs and charts need descriptions that summarize their meaning.aria-describedby
for data visualizations: Long descriptions can be linked to charts so screen readers provide full context.I once posted a project screenshot without alt text. When testing with a screen reader, all I heard was "image." Not helpful. Adding descriptive alt text like "Portfolio homepage with hero banner and navigation menu" fixed that.
<!-- Decorative image -->
<img src="decorative-line.png" alt="" aria-hidden="true">
<!-- Informative image -->
<img src="portfolio-home.png" alt="Screenshot of portfolio homepage with hero banner and navigation menu">
<!-- Data visualization -->
<figure>
<img
src="traffic-growth.png"
alt="Bar chart showing traffic growth per month"
aria-describedby="trafficData">
<figcaption id="trafficData">
Site traffic increased steadily from January to June, doubling in total sessions.
</figcaption>
</figure>
Color choices often make or break accessibility. WCAG requires a contrast ratio of at least 4.5:1 for normal text.
I had a hero section on rguidry.dev with white text over a bright orange background. Looked fine to me. But when I ran it through a contrast checker, it failed WCAG standards. Switching to a darker overlay fixed it without killing the design.
/* BAD contrast */
.low-contrast {
color: #fff;
background-color: #ffcc66; /* Fails WCAG AA */
}
/* GOOD contrast */
.high-contrast {
color: #fff;
background-color: #cc6600; /* Passes WCAG AA */
}
Dynamic content is common, but it often breaks screen reader usability.
aria-live
regions: Dynamic updates (like form validation) must announce changes.aria-hidden
for decorative elements: Decorative icons shouldn't clutter the accessibility tree.aria-label
for complex sections: Landmarks like sidebars or carousels need labels to distinguish them.On my site, I had a "copy email" button that showed "Copied!" after clicking. Without an aria-live region, screen readers didn't announce the change. Adding it made the feature usable.
<button onclick="copyEmail()">Copy Email</button>
<div id="notification" aria-live="polite"></div>
<script>
function copyEmail() {
// Note: In a real app, use a more robust clipboard method.
document.getElementById("notification").textContent = "Copied!";
}
</script>
Accessibility isn't a checklist you tick once. Standards evolve, content changes, and new features add risk. Every deployment should include automated and manual accessibility checks.
For rguidry.dev, I set up continuous auditing with Lighthouse and axe-core. Each commit now runs automated scans. If contrast ratios dip or ARIA attributes are missing, the build fails. That feedback loop keeps accessibility a living standard, not a forgotten task.
Some developers see accessibility as overhead. In reality, it's leverage.
When I rebuilt rguidry.dev with accessibility in mind, recruiters actually commented on it. Not the design polish, but the care taken to make it usable.
Accessibility is critical infrastructure for the web. It's not charity. It's not optional. It's how the web should work. WCAG provides the framework. Implementing it means better usability, stronger SEO, and a wider reach.
When you're building your siteâwhether it's a personal project like rguidry.dev or a large-scale appâstart with semantic HTML, add ARIA roles, fix forms, write alt text, check contrast, ensure keyboard navigation, and optimize for screen readers. The payoff isn't just compliance. It's a website that works for everyone and ranks where it should.
For more insights on building better systems, check out my reflections on higher education reformâanother area where accessibility and user experience principles can drive meaningful change.