<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Denis Omerovic</title>
    <description>The latest articles on DEV Community by Denis Omerovic (@chille87).</description>
    <link>https://dev.to/chille87</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3016792%2F2823df19-1334-438f-a4ad-f592800a3f19.jpg</url>
      <title>DEV Community: Denis Omerovic</title>
      <link>https://dev.to/chille87</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chille87"/>
    <language>en</language>
    <item>
      <title>WCAG Color Contrast: Meeting AA &amp; AAA Without Killing Design</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Sun, 20 Sep 2026 21:14:26 +0000</pubDate>
      <link>https://dev.to/chille87/wcag-color-contrast-meeting-aa-aaa-without-killing-design-376f</link>
      <guid>https://dev.to/chille87/wcag-color-contrast-meeting-aa-aaa-without-killing-design-376f</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://getaccessguard.com/posts/color-contrast-and-accessibility-a-designers-guide" rel="noopener noreferrer"&gt;AccessGuard&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;Color contrast is the most common accessibility failure&lt;/h2&gt;

&lt;p&gt;If there's one accessibility issue that appears on nearly every website, it's insufficient color contrast. The &lt;a href="https://webaim.org/projects/million/" rel="noopener noreferrer"&gt;WebAIM Million study&lt;/a&gt; found low contrast text on 83.9% of the home pages it tested in 2026, which makes it the single most widespread WCAG failure on the web.&lt;/p&gt;

&lt;p&gt;The reason is straightforward: designers choose colors that look good on their own high-resolution monitors in well-lit offices. For anyone with low vision, a color vision deficiency or age-related sight changes, those subtle grays and trendy pastels can render text unreadable.&lt;/p&gt;

&lt;p&gt;This guide explains the WCAG contrast requirements, identifies the most common problem areas, and shows you how to maintain beautiful design while meeting accessibility standards.&lt;/p&gt;

&lt;h2&gt;Understanding contrast ratios&lt;/h2&gt;

&lt;p&gt;WCAG measures color contrast as a ratio between the luminance (perceived brightness) of the foreground color and the background color. The scale runs from 1:1 (no contrast - same color on same color) to 21:1 (maximum contrast - black on white).&lt;/p&gt;

&lt;p&gt;The standard defines three threshold levels:&lt;/p&gt;

&lt;h3&gt;WCAG AA - The practical minimum&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Normal text&lt;/strong&gt; (under 18pt / 24px, or under 14pt / 18.5px bold): minimum &lt;strong&gt;4.5:1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large text&lt;/strong&gt; (18pt+ / 24px+, or 14pt+ / 18.5px+ bold): minimum &lt;strong&gt;3:1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI components and graphical objects&lt;/strong&gt; (icons, form borders, focus indicators): minimum &lt;strong&gt;3:1&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Level AA is the standard most laws require and the level you should target for compliance.&lt;/p&gt;

&lt;h3&gt;WCAG AAA - The gold standard&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Normal text:&lt;/strong&gt; minimum &lt;strong&gt;7:1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large text:&lt;/strong&gt; minimum &lt;strong&gt;4.5:1&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Level AAA isn't required by most regulations, but meeting it where feasible improves readability for everyone - not just users with disabilities.&lt;/p&gt;

&lt;h3&gt;What counts as "large text"?&lt;/h3&gt;

&lt;p&gt;WCAG defines large text as 18pt (24px) or larger at regular weight, or 14pt (18.5px) or larger at bold weight. Large text gets a lower contrast threshold because its size makes it inherently easier to read. But be careful - 18px, a common body font size in modern design, is &lt;em&gt;not&lt;/em&gt; large text by WCAG standards. You need 24px or larger.&lt;/p&gt;

&lt;h2&gt;Common contrast problem areas&lt;/h2&gt;

&lt;p&gt;Certain design patterns consistently fail contrast requirements. Knowing where to look saves time during audits.&lt;/p&gt;

&lt;h3&gt;Light gray text on white&lt;/h3&gt;

&lt;p&gt;This is the most common offender. Designers use light gray for "secondary" text - timestamps, captions, metadata - to create visual hierarchy. But the result often fails contrast standards.&lt;/p&gt;

&lt;p&gt;The lightest gray that passes 4.5:1 against pure white (&lt;code&gt;#FFFFFF&lt;/code&gt;) is &lt;code&gt;#767676&lt;/code&gt;, at 4.54:1. Anything lighter fails. That popular &lt;code&gt;#999999&lt;/code&gt; many designers reach for? It only achieves 2.85:1, well below the minimum.&lt;/p&gt;

&lt;h3&gt;Placeholder text in forms&lt;/h3&gt;

&lt;p&gt;Browser default placeholder colors typically fail contrast requirements. Chrome's default placeholder color on a white input is approximately &lt;code&gt;#757575&lt;/code&gt;, which barely passes at 4.61:1. But if your input has a light gray background, even that might fail. Custom-styled placeholders in lighter shades almost always fail.&lt;/p&gt;

&lt;p&gt;Remember that placeholder text should never replace labels, but when you do use it, it still needs to be readable.&lt;/p&gt;

&lt;h3&gt;Text overlaid on images&lt;/h3&gt;

&lt;p&gt;Hero banners and cards with text over photographs are a contrast minefield. The contrast varies depending on the image content beneath the text - it might pass in one area and fail in another.&lt;/p&gt;

&lt;p&gt;Solutions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a &lt;strong&gt;semi-transparent overlay&lt;/strong&gt; between the image and text&lt;/li&gt;
&lt;li&gt;Using a &lt;strong&gt;solid background behind the text&lt;/strong&gt; area&lt;/li&gt;
&lt;li&gt;Adding a &lt;strong&gt;text shadow&lt;/strong&gt; for additional separation (though this alone may not be sufficient)&lt;/li&gt;
&lt;li&gt;Choosing images with &lt;strong&gt;consistent dark or light areas&lt;/strong&gt; where text is placed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Colored buttons and links&lt;/h3&gt;

&lt;p&gt;Brand-colored buttons often fail when light brand colors are used with white text, or dark brand colors with dark text. A medium blue button with white text might look fine but fail the 4.5:1 threshold.&lt;/p&gt;

&lt;p&gt;Links that rely solely on color to distinguish them from surrounding text have an additional requirement: the color difference between the link and the surrounding text must be at least 3:1 (or the link must have a non-color indicator like an underline).&lt;/p&gt;

&lt;h3&gt;Disabled and inactive states&lt;/h3&gt;

&lt;p&gt;WCAG technically exempts "inactive" UI components from contrast requirements, so disabled buttons and inputs don't need to meet the 4.5:1 threshold. However, users still need to perceive that a control exists and is disabled. Using extremely low contrast for disabled states can make them invisible, confusing users about what options are available.&lt;/p&gt;

&lt;h2&gt;Maintaining your brand while meeting standards&lt;/h2&gt;

&lt;p&gt;A common concern from design teams is that accessibility requirements will force them to abandon their brand colors. In practice, this is rarely the case. Here are strategies that work:&lt;/p&gt;

&lt;h3&gt;Darken, don't replace&lt;/h3&gt;

&lt;p&gt;Most brand colors that fail contrast can be adjusted by darkening the shade slightly. If your brand blue is &lt;code&gt;#4A90D9&lt;/code&gt; (3.34:1 against white), shifting to &lt;code&gt;#2A6AB5&lt;/code&gt; (5.49:1) keeps the same hue while passing AA. Most users will not notice the difference. Users with low vision will notice the improvement.&lt;/p&gt;

&lt;h3&gt;Use color strategically&lt;/h3&gt;

&lt;p&gt;You can still use your lighter brand colors in places where contrast requirements are less strict: large headings (3:1 threshold), decorative elements (no contrast requirement), backgrounds, and borders. Reserve your darkened accessible variants for body text, buttons, and form elements.&lt;/p&gt;

&lt;h3&gt;Test early in the design process&lt;/h3&gt;

&lt;p&gt;Checking contrast after the design is "done" leads to frustrating last-minute changes. Build contrast checking into your design workflow from the start. Many design tools have built-in or plugin-based contrast checkers that give you real-time feedback as you choose colors.&lt;/p&gt;

&lt;h2&gt;Tools for checking contrast&lt;/h2&gt;

&lt;p&gt;You don't need to calculate contrast ratios by hand. These tools make checking quick and easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser DevTools&lt;/strong&gt; - Chrome, Firefox, and Edge all show contrast ratios when you inspect text elements. Chrome's color picker also suggests colors that would meet AA and AAA thresholds.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webaim.org/resources/contrastchecker/" rel="noopener noreferrer"&gt;&lt;strong&gt;WebAIM Contrast Checker&lt;/strong&gt;&lt;/a&gt; - A simple web tool where you enter foreground and background hex codes and see the resulting ratio.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.figma.com/community/plugin/733159460536249875" rel="noopener noreferrer"&gt;&lt;strong&gt;Stark&lt;/strong&gt;&lt;/a&gt; - A popular plugin for Figma, Sketch, and Adobe XD that checks contrast within your design tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operating system tools&lt;/strong&gt; - macOS includes a Digital Color Meter and accessibility inspector. Windows has the Accessibility Insights tool from Microsoft.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;How AccessGuard helps with color contrast&lt;/h2&gt;

&lt;p&gt;Checking individual color pairs works well during design, but a live site may have hundreds of text elements across dozens of pages. AccessGuard runs automated WCAG 2.2 AA checks in a real browser and flags every text element that falls below the threshold for its size.&lt;/p&gt;

&lt;p&gt;Each contrast issue comes with the two colors found, the calculated ratio, the ratio required at that text size, and the WCAG criterion it fails, so your design team gets the exact pair to change rather than a page to go hunting through. Reports can go out as white-label PDFs under your agency's name.&lt;/p&gt;

&lt;p&gt;Contrast is one of the failures automated checks are genuinely good at, because the ratio is arithmetic. Text over photographs is the exception: a tool can only measure against the pixels it samples, so hero images still need a human eye. Automated checks find many problems but cannot confirm conformance.&lt;/p&gt;

&lt;h2&gt;Next steps for your team&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Set the accessible variants of your brand colors as design tokens, so nobody has to remember which blue passes.&lt;/li&gt;
&lt;li&gt;Check every new color pair at design time, not at QA.&lt;/li&gt;
&lt;li&gt;Give focus indicators and form borders their own 3:1 check. They are the ones teams forget.&lt;/li&gt;
&lt;li&gt;Scan the live templates after each release, because a CSS change can undo a fix quietly.&lt;/li&gt;
&lt;li&gt;Review text over images by hand on the breakpoints you support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See what a scan reports for one of your pages with the &lt;a href="https://getaccessguard.com/checks/color-contrast" rel="noopener noreferrer"&gt;color contrast checker&lt;/a&gt;, or &lt;a href="https://getaccessguard.com/scan" rel="noopener noreferrer"&gt;run a free scan&lt;/a&gt; on a client page. For the wider audit, read &lt;a href="https://getaccessguard.com/posts/how-to-audit-your-website-for-accessibility" rel="noopener noreferrer"&gt;how to audit a website for accessibility&lt;/a&gt; and &lt;a href="https://getaccessguard.com/posts/most-common-accessibility-issues-and-how-to-fix-them" rel="noopener noreferrer"&gt;the most common accessibility issues and how to fix them&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>Most Common WCAG Violations (With Code Fixes for Each)</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Fri, 18 Sep 2026 07:16:55 +0000</pubDate>
      <link>https://dev.to/chille87/most-common-wcag-violations-with-code-fixes-for-each-51n6</link>
      <guid>https://dev.to/chille87/most-common-wcag-violations-with-code-fixes-for-each-51n6</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://getaccessguard.com/posts/most-common-accessibility-issues-and-how-to-fix-them" rel="noopener noreferrer"&gt;AccessGuard&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;The same issues keep showing up&lt;/h2&gt;

&lt;p&gt;Every year, the &lt;a href="https://webaim.org/projects/million/" rel="noopener noreferrer"&gt;WebAIM Million study&lt;/a&gt; analyzes the top one million websites for accessibility. And every year, the results tell a remarkably consistent story: a small set of issues accounts for the vast majority of failures.&lt;/p&gt;

&lt;p&gt;In the 2026 report, 95.9% of home pages had detected WCAG 2 failures, at an average of 56.1 errors per page, and 96% of all detected errors fell into just six categories: low contrast text, missing alt text, missing form input labels, empty links, empty buttons and missing document language. That means a handful of common problems account for nearly all of what an automated scan will find. It also means the count went the wrong way this year: WebAIM records a 10.1% rise in detected errors per page since its 2025 analysis.&lt;/p&gt;

&lt;p&gt;This post walks through the most common accessibility issues found in real-world scans, explains why each one matters, and gives you the exact code to fix it.&lt;/p&gt;

&lt;h2&gt;1. Missing image alt text&lt;/h2&gt;

&lt;h3&gt;Why it matters&lt;/h3&gt;

&lt;p&gt;When an image lacks alt text, screen reader users hear something like "image" or the file name - &lt;em&gt;"DSC_0492.jpg"&lt;/em&gt; - which conveys no meaning. For users who rely on screen readers, images without alt text are invisible at best and confusing at worst.&lt;/p&gt;

&lt;p&gt;Missing alt text violates &lt;strong&gt;WCAG 1.1.1 Non-text Content (Level A)&lt;/strong&gt;, the most fundamental accessibility requirement.&lt;/p&gt;

&lt;h3&gt;How to fix it&lt;/h3&gt;

&lt;p&gt;Every image needs an &lt;code&gt;alt&lt;/code&gt; attribute. What you put in it depends on the image's purpose:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Informational images&lt;/strong&gt; - describe what the image conveys:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;img src="team-photo.jpg" alt="The AccessGuard team at our 2024 company retreat"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functional images&lt;/strong&gt; (like icons inside links or buttons) - describe the action:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;a href="/search"&amp;gt;&amp;lt;img src="search-icon.svg" alt="Search"&amp;gt;&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decorative images&lt;/strong&gt; that add no information - use an empty alt attribute so screen readers skip them entirely:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;img src="decorative-swoosh.svg" alt=""&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The key principle: alt text should convey the &lt;strong&gt;purpose&lt;/strong&gt; of the image, not just describe its appearance. "Photo of a woman" is rarely useful. "CEO Maria Lopez presenting quarterly results" tells the user what they need to know.&lt;/p&gt;

&lt;h2&gt;2. Low color contrast&lt;/h2&gt;

&lt;h3&gt;Why it matters&lt;/h3&gt;

&lt;p&gt;Low contrast text is difficult or impossible to read for people with low vision, color blindness, or anyone using a screen in bright sunlight. It's one of the most common accessibility failures - the 2026 WebAIM Million found it on 83.9% of home pages, which makes it the single most common failure type.&lt;/p&gt;

&lt;p&gt;Low contrast violates &lt;strong&gt;WCAG 1.4.3 Contrast Minimum (Level AA)&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;The required ratios&lt;/h3&gt;

&lt;p&gt;WCAG defines minimum contrast ratios between text color and its background:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Normal text&lt;/strong&gt; (under 18pt, or under 14pt bold): minimum &lt;strong&gt;4.5:1&lt;/strong&gt; ratio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large text&lt;/strong&gt; (18pt+, or 14pt+ bold): minimum &lt;strong&gt;3:1&lt;/strong&gt; ratio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI components and graphical objects&lt;/strong&gt;: minimum &lt;strong&gt;3:1&lt;/strong&gt; ratio&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;How to fix it&lt;/h3&gt;

&lt;p&gt;First, check your current contrast ratios. You can use browser DevTools - Chrome's color picker shows the contrast ratio directly. You can also use online tools like the &lt;a href="https://webaim.org/resources/contrastchecker/" rel="noopener noreferrer"&gt;WebAIM Contrast Checker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Common problem areas to audit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Light gray text on white backgrounds&lt;/strong&gt; - a frequent design choice that almost always fails. &lt;code&gt;color: #767676&lt;/code&gt; is the lightest gray that passes 4.5:1 against white&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Placeholder text in form fields&lt;/strong&gt; - browser default placeholder color often fails contrast requirements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text overlaid on images&lt;/strong&gt; - without a solid background or text shadow, contrast varies by the underlying image content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Links that are only distinguished by color&lt;/strong&gt; - if links aren't underlined, the color difference from surrounding text must meet a 3:1 ratio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When adjusting colors, you don't need to abandon your brand palette. Often, using a slightly darker shade of the same hue is enough to pass. For example, if your brand blue is &lt;code&gt;#5B9FD6&lt;/code&gt;, it fails against white at 2.85:1. Darkening it to &lt;code&gt;#2B6CA3&lt;/code&gt; gives 5.56:1, which clears 4.5:1 with room to spare and keeps the same feel. Our &lt;a href="https://getaccessguard.com/checks/color-contrast" rel="noopener noreferrer"&gt;color contrast checker&lt;/a&gt; explains how the ratio is calculated, and &lt;a href="https://getaccessguard.com/posts/color-contrast-and-accessibility-a-designers-guide" rel="noopener noreferrer"&gt;meeting AA without killing the design&lt;/a&gt; covers the palette work in more detail.&lt;/p&gt;

&lt;h2&gt;3. Missing form labels&lt;/h2&gt;

&lt;h3&gt;Why it matters&lt;/h3&gt;

&lt;p&gt;When a form input doesn't have a properly associated label, screen reader users don't know what information to enter. They hear "edit text" with no context - is it asking for their name, email, or credit card number? This creates a guessing game that makes forms unusable.&lt;/p&gt;

&lt;p&gt;Missing form labels violate &lt;strong&gt;WCAG 1.3.1 Info and Relationships (Level A)&lt;/strong&gt; and &lt;strong&gt;WCAG 4.1.2 Name, Role, Value (Level A)&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;How to fix it&lt;/h3&gt;

&lt;p&gt;Every form input needs a programmatically associated label. The most reliable method is the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; element with a &lt;code&gt;for&lt;/code&gt; attribute that matches the input's &lt;code&gt;id&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;label for="email"&amp;gt;Email address&amp;lt;/label&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;lt;input type="email" id="email" name="email"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Alternatively, you can wrap the input inside the label:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;label&amp;gt;Email address &amp;lt;input type="email" name="email"&amp;gt;&amp;lt;/label&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;Common mistakes to avoid&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Using placeholder as a label.&lt;/strong&gt; Placeholder text disappears when the user starts typing, removing the only indication of what the field is for. It also typically fails contrast requirements. Always use a visible &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; in addition to any placeholder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using &lt;code&gt;aria-label&lt;/code&gt; instead of a visible label.&lt;/strong&gt; While &lt;code&gt;aria-label&lt;/code&gt; is announced by screen readers, sighted users who rely on the label for context (including people with cognitive disabilities) won't benefit. Prefer visible labels whenever possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forgetting labels on select, textarea, and checkbox elements.&lt;/strong&gt; Every form control needs a label - not just text inputs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;4. Broken heading hierarchy&lt;/h2&gt;

&lt;h3&gt;Why it matters&lt;/h3&gt;

&lt;p&gt;Headings aren't just visual formatting - they create a structural outline of your page. Screen reader users rely heavily on headings to navigate: most screen readers let users jump between headings with a single keystroke, and many users scan headings first to find the section they need, just like sighted users scan visual hierarchy.&lt;/p&gt;

&lt;p&gt;Skipping heading levels (jumping from &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;h4&amp;gt;&lt;/code&gt;) or using headings purely for styling (making something an &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; because you want smaller bold text) breaks this navigation and violates &lt;strong&gt;WCAG 1.3.1 Info and Relationships (Level A)&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;How to fix it&lt;/h3&gt;

&lt;p&gt;Follow these rules for a correct heading structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; per page&lt;/strong&gt; - this should be the main topic or title of the page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't skip levels&lt;/strong&gt; - an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; should be followed by &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;, never &lt;code&gt;&amp;lt;h4&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use headings for structure, not styling&lt;/strong&gt; - if you want smaller bold text, use CSS instead of a lower heading level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A correct heading outline looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Page Title&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;lt;h2&amp;gt;Main Section&amp;lt;/h2&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;h3&amp;gt;Subsection&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;h3&amp;gt;Subsection&amp;lt;/h3&amp;gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;lt;h2&amp;gt;Another Main Section&amp;lt;/h2&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Think of headings like a table of contents. If the outline doesn't make sense when listed on its own, your heading structure needs work.&lt;/p&gt;

&lt;h2&gt;5. Missing document language&lt;/h2&gt;

&lt;h3&gt;Why it matters&lt;/h3&gt;

&lt;p&gt;When the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element doesn't include a &lt;code&gt;lang&lt;/code&gt; attribute, screen readers don't know what language to use for pronunciation. A French screen reader user visiting an English page might hear English words pronounced with French phonetics - rendering the content incomprehensible.&lt;/p&gt;

&lt;p&gt;This is arguably the easiest accessibility fix, yet the 2026 WebAIM Million found it missing on 13.5% of home pages. It violates &lt;strong&gt;WCAG 3.1.1 Language of Page (Level A)&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;How to fix it&lt;/h3&gt;

&lt;p&gt;Add a &lt;code&gt;lang&lt;/code&gt; attribute to your &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;html lang="en"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Use the appropriate &lt;a href="https://www.w3.org/International/articles/language-tags/" rel="noopener noreferrer"&gt;IETF language tag&lt;/a&gt; for your content's primary language. Common values include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;en&lt;/code&gt; - English&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;es&lt;/code&gt; - Spanish&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fr&lt;/code&gt; - French&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;de&lt;/code&gt; - German&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zh&lt;/code&gt; - Chinese&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ja&lt;/code&gt; - Japanese&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your page contains sections in a different language, add a &lt;code&gt;lang&lt;/code&gt; attribute to those sections as well:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;p&amp;gt;The French word &amp;lt;span lang="fr"&amp;gt;accessibilité&amp;lt;/span&amp;gt; translates to accessibility.&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This one-line fix takes seconds to implement and immediately helps every screen reader user who visits your site.&lt;/p&gt;

&lt;h2&gt;The pattern behind these issues&lt;/h2&gt;

&lt;p&gt;Notice something these five issues have in common? Four of the five are &lt;strong&gt;Level A&lt;/strong&gt; failures, the most basic tier of WCAG, and low contrast is Level AA. They are also all straightforward to fix, often needing a single line of HTML. For the ones that need more than that, &lt;a href="https://getaccessguard.com/posts/accessible-forms-how-to-build-inputs-every-user-can-complete" rel="noopener noreferrer"&gt;accessible forms&lt;/a&gt; and &lt;a href="https://getaccessguard.com/posts/alt-text-done-right-writing-image-descriptions-that-work" rel="noopener noreferrer"&gt;how to write alt text&lt;/a&gt; go deeper.&lt;/p&gt;

&lt;p&gt;The gap between inaccessible and accessible isn't a chasm of complexity. It's a collection of small, fixable oversights - missing attributes, forgotten labels, unchecked contrast. The barrier to meaningful improvement is awareness, not difficulty.&lt;/p&gt;

&lt;h2&gt;How AccessGuard helps you find and fix these issues&lt;/h2&gt;

&lt;p&gt;You could audit every page by hand, but on a growing site that stops being practical. AccessGuard runs automated WCAG 2.2 AA checks in a real browser and flags every instance of these common problems and many more. You can try it on any page with a &lt;a href="https://getaccessguard.com/scan" rel="noopener noreferrer"&gt;free accessibility scan&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each issue in the report names the WCAG criterion it fails, its severity, and the exact element on the page. On paid plans it also writes the fix. Reports go out white-labelled under your agency's name, and every client site sits in one account so you can see what broke and what got fixed since the last scan.&lt;/p&gt;

&lt;p&gt;What a scan cannot do is tell you the site conforms. Automated checks find many real problems, and whether alt text is accurate, whether focus order makes sense in a real flow and whether an error message actually helps still need a person. The check pages set out what each test covers, for example the &lt;a href="https://getaccessguard.com/checks/alt-text" rel="noopener noreferrer"&gt;alt text checker&lt;/a&gt; and the &lt;a href="https://getaccessguard.com/checks/form-labels" rel="noopener noreferrer"&gt;form labels checker&lt;/a&gt;, and the &lt;a href="https://getaccessguard.com/posts/how-to-audit-your-website-for-accessibility" rel="noopener noreferrer"&gt;accessibility audit checklist&lt;/a&gt; covers the manual steps that go around the scan.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>wcag</category>
    </item>
    <item>
      <title>What Is WCAG? A Plain-English Guide to 2.0, 2.1 and 2.2</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Wed, 16 Sep 2026 07:13:18 +0000</pubDate>
      <link>https://dev.to/chille87/what-is-wcag-a-plain-english-guide-to-20-21-and-22-376l</link>
      <guid>https://dev.to/chille87/what-is-wcag-a-plain-english-guide-to-20-21-and-22-376l</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://getaccessguard.com/posts/understanding-wcag-the-standard-behind-accessible-websites" rel="noopener noreferrer"&gt;AccessGuard&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;WCAG doesn't have to be intimidating&lt;/h2&gt;

&lt;p&gt;If you've ever looked into web accessibility, you've probably encountered the acronym WCAG - and then promptly felt overwhelmed. The Web Content Accessibility Guidelines are the global standard for accessible web design, referenced by laws and regulations in dozens of countries. But reading the actual specification can feel like deciphering legal code written by engineers.&lt;/p&gt;

&lt;p&gt;The good news? You don't need to memorize every success criterion. Once you understand the structure and principles behind WCAG, the standard becomes a practical tool rather than an intimidating document. This post breaks it all down in plain language.&lt;/p&gt;

&lt;h2&gt;What is WCAG?&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Web Content Accessibility Guidelines (WCAG)&lt;/strong&gt; are a set of recommendations for making web content more accessible to people with disabilities. They're developed and maintained by the &lt;strong&gt;Web Accessibility Initiative (WAI)&lt;/strong&gt;, which is part of the &lt;strong&gt;World Wide Web Consortium (W3C)&lt;/strong&gt; - the same organization that develops HTML, CSS, and other core web standards.&lt;/p&gt;

&lt;p&gt;WCAG has evolved through several versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WCAG 1.0 (1999)&lt;/strong&gt; - The original guidelines, now largely obsolete. They were tied to specific HTML techniques and didn't age well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WCAG 2.0 (2008)&lt;/strong&gt; - A major rewrite that introduced technology-agnostic principles. Still widely referenced and forms the foundation of most accessibility laws.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WCAG 2.1 (2018)&lt;/strong&gt; - Added 17 new success criteria addressing mobile accessibility, low vision, and cognitive disabilities. This is the version most commonly required today.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WCAG 2.2 (2023)&lt;/strong&gt; - The latest release, adding 9 new criteria focused on users with cognitive disabilities, low vision, and mobile devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each new version builds on the previous one - all WCAG 2.0 criteria still apply in 2.1, and all 2.1 criteria still apply in 2.2. Think of it as additive, not replacing.&lt;/p&gt;

&lt;h2&gt;The four principles: POUR&lt;/h2&gt;

&lt;p&gt;At its heart, WCAG is organized around four principles. Every success criterion falls under one of these. They spell out the acronym &lt;strong&gt;POUR&lt;/strong&gt;, and they answer a simple question: what does a user need from web content?&lt;/p&gt;

&lt;h3&gt;1. Perceivable&lt;/h3&gt;

&lt;p&gt;Users must be able to &lt;strong&gt;perceive&lt;/strong&gt; the information being presented. Content can't be invisible to all of a user's senses.&lt;/p&gt;

&lt;p&gt;In practice, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images need &lt;strong&gt;alt text&lt;/strong&gt; so screen reader users know what they depict&lt;/li&gt;
&lt;li&gt;Videos need &lt;strong&gt;captions&lt;/strong&gt; so deaf and hard-of-hearing users can follow along&lt;/li&gt;
&lt;li&gt;Text needs sufficient &lt;strong&gt;color contrast&lt;/strong&gt; against its background so low-vision users can read it&lt;/li&gt;
&lt;li&gt;Content shouldn't rely on &lt;strong&gt;color alone&lt;/strong&gt; to convey meaning (e.g., "fields marked in red are required" fails if someone can't see red)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key idea: if someone can't perceive your content through at least one sense, it doesn't exist for them.&lt;/p&gt;

&lt;h3&gt;2. Operable&lt;/h3&gt;

&lt;p&gt;Users must be able to &lt;strong&gt;operate&lt;/strong&gt; the interface. Every interactive element must be usable regardless of how someone navigates.&lt;/p&gt;

&lt;p&gt;In practice, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everything that works with a mouse must also work with a &lt;strong&gt;keyboard&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Users must have &lt;strong&gt;enough time&lt;/strong&gt; to read and interact with content - no auto-advancing carousels that move too fast&lt;/li&gt;
&lt;li&gt;Content should not &lt;strong&gt;flash&lt;/strong&gt; in ways that could trigger seizures&lt;/li&gt;
&lt;li&gt;Users need clear &lt;strong&gt;navigation&lt;/strong&gt; mechanisms - skip links, descriptive page titles, logical focus order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key idea: a beautiful interface is useless if someone can't actually use it.&lt;/p&gt;

&lt;h3&gt;3. Understandable&lt;/h3&gt;

&lt;p&gt;Users must be able to &lt;strong&gt;understand&lt;/strong&gt; both the information and how the interface works. Content should be readable, and the site should behave predictably.&lt;/p&gt;

&lt;p&gt;In practice, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;language&lt;/strong&gt; of the page is identified in the HTML (so screen readers use the correct pronunciation)&lt;/li&gt;
&lt;li&gt;Navigation is &lt;strong&gt;consistent&lt;/strong&gt; across pages&lt;/li&gt;
&lt;li&gt;Form inputs have clear &lt;strong&gt;labels&lt;/strong&gt; and &lt;strong&gt;error messages&lt;/strong&gt; that explain what went wrong and how to fix it&lt;/li&gt;
&lt;li&gt;Unusual words or abbreviations are &lt;strong&gt;defined&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key idea: clarity isn't just good writing - it's an accessibility requirement.&lt;/p&gt;

&lt;h3&gt;4. Robust&lt;/h3&gt;

&lt;p&gt;Content must be &lt;strong&gt;robust&lt;/strong&gt; enough to be interpreted reliably by a wide range of technologies, including assistive technologies like screen readers.&lt;/p&gt;

&lt;p&gt;In practice, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML is &lt;strong&gt;well-formed&lt;/strong&gt; and valid - proper opening and closing tags, unique IDs&lt;/li&gt;
&lt;li&gt;Custom components use appropriate &lt;strong&gt;ARIA roles and properties&lt;/strong&gt; so assistive technologies can understand them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status messages&lt;/strong&gt; are programmatically communicated without requiring focus changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key idea: your content should work not just in today's browsers, but with the assistive technologies your users actually rely on.&lt;/p&gt;

&lt;h2&gt;Conformance levels: A, AA, and AAA&lt;/h2&gt;

&lt;p&gt;Each WCAG success criterion is assigned one of three conformance levels. These indicate the impact and difficulty of meeting the requirement:&lt;/p&gt;

&lt;h3&gt;Level A - The baseline&lt;/h3&gt;

&lt;p&gt;These are the most fundamental requirements. Failing Level A means your site has &lt;strong&gt;serious barriers&lt;/strong&gt; that will completely block some users. Examples include providing alt text for images and ensuring all functionality is available via keyboard.&lt;/p&gt;

&lt;h3&gt;Level AA - The practical standard&lt;/h3&gt;

&lt;p&gt;Level AA addresses the &lt;strong&gt;most common barriers&lt;/strong&gt; people with disabilities encounter. This is the level referenced by most laws and regulations worldwide - including the ADA, the European Accessibility Act, and Section 508. Examples include meeting minimum color contrast ratios (4.5:1 for normal text) and providing visible focus indicators.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you're aiming for one level, aim for AA.&lt;/strong&gt; It's the sweet spot between meaningful impact and practical feasibility.&lt;/p&gt;

&lt;h3&gt;Level AAA - The gold standard&lt;/h3&gt;

&lt;p&gt;Level AAA represents the &lt;strong&gt;highest level of accessibility&lt;/strong&gt;. These criteria are often difficult to achieve for all types of content - for example, requiring a contrast ratio of 7:1 or providing sign language interpretation for all video. W3C itself states that it's not recommended to require AAA conformance as a general policy, because it's not always possible.&lt;/p&gt;

&lt;p&gt;That said, meeting individual AAA criteria where feasible (like enhanced contrast) is excellent practice.&lt;/p&gt;

&lt;h2&gt;How to read a success criterion&lt;/h2&gt;

&lt;p&gt;Each WCAG success criterion follows a consistent structure. Let's break down a real example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.4.3 Contrast (Minimum) - Level AA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's what each part tells you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1&lt;/strong&gt; - The principle (1 = Perceivable)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4&lt;/strong&gt; - The guideline within that principle (1.4 = Distinguishable)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3&lt;/strong&gt; - The specific success criterion number&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contrast (Minimum)&lt;/strong&gt; - The human-readable name&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level AA&lt;/strong&gt; - The conformance level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The criterion itself states: &lt;em&gt;"The visual presentation of text and images of text has a contrast ratio of at least 4.5:1"&lt;/em&gt; (with exceptions for large text, incidental text, and logotypes).&lt;/p&gt;

&lt;p&gt;Beyond the criterion text, WCAG provides &lt;strong&gt;techniques&lt;/strong&gt; - specific implementation approaches that satisfy the requirement. Techniques are categorized as "sufficient" (guaranteed to pass), "advisory" (recommended but not required), and "failures" (guaranteed to fail). This layered structure means you can understand both &lt;em&gt;what&lt;/em&gt; to achieve and &lt;em&gt;how&lt;/em&gt; to achieve it.&lt;/p&gt;

&lt;h2&gt;WCAG 2.1 vs. 2.2: What changed?&lt;/h2&gt;

&lt;p&gt;If you're already working toward WCAG 2.1 compliance, you're in good shape. WCAG 2.2 adds a targeted set of improvements, mostly benefiting users with cognitive disabilities, low vision, and mobile device users:&lt;/p&gt;

&lt;h3&gt;Key additions in WCAG 2.2&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Focus Appearance (2.4.13, AA)&lt;/strong&gt; - Focus indicators must meet minimum size and contrast requirements, ending the era of invisible or barely-visible outlines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dragging Movements (2.5.7, AA)&lt;/strong&gt; - Any action that requires dragging must also have a non-dragging alternative (like click-to-move), helping users with motor impairments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessible Authentication (3.3.8, AA)&lt;/strong&gt; - Login flows cannot require cognitive function tests (like remembering a password or solving a puzzle) without providing alternatives like password managers or biometric options&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent Help (3.2.6, A)&lt;/strong&gt; - If a help mechanism (like a chat widget or contact link) appears on multiple pages, it must be in the same relative location&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redundant Entry (3.3.7, A)&lt;/strong&gt; - Information a user has already entered in a process should be auto-populated or available to select, rather than requiring them to re-enter it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One notable change: &lt;strong&gt;4.1.1 Parsing&lt;/strong&gt; was removed in WCAG 2.2. Modern browsers and assistive technologies have become robust enough at handling markup errors that this criterion is no longer considered necessary.&lt;/p&gt;

&lt;h2&gt;How AccessGuard maps to WCAG&lt;/h2&gt;

&lt;p&gt;Understanding WCAG is valuable, but manually checking your site against dozens of success criteria is time-consuming and error-prone. This is where automated scanning becomes essential.&lt;/p&gt;

&lt;p&gt;AccessGuard scans your website and maps every issue it finds to a &lt;strong&gt;specific WCAG success criterion&lt;/strong&gt;. Each issue includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;criterion number and name&lt;/strong&gt; (e.g., 1.4.3 Contrast Minimum)&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;conformance level&lt;/strong&gt; (A, AA, or AAA)&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;severity rating&lt;/strong&gt; - error, warning, or notice - so you can prioritize what to fix first&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-written fix suggestions&lt;/strong&gt; on paid plans, explaining what to change in your code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means you don't need to cross-reference the WCAG specification yourself. AccessGuard connects the dots between the issue on your page and the standard it violates, then tells you how to fix it.&lt;/p&gt;

&lt;p&gt;Now that you understand the structure behind WCAG, you can read your scan results with confidence and make informed decisions about which issues to address first. Automated checks find many problems but cannot confirm conformance, so pair every scan with a manual pass over each template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://getaccessguard.com/scan" rel="noopener noreferrer"&gt;Run a free scan&lt;/a&gt; on a client page to see the criteria in context, or start with &lt;a href="https://getaccessguard.com/posts/most-common-accessibility-issues-and-how-to-fix-them" rel="noopener noreferrer"&gt;the most common accessibility issues and how to fix them&lt;/a&gt; and &lt;a href="https://getaccessguard.com/posts/how-to-audit-your-website-for-accessibility" rel="noopener noreferrer"&gt;how to audit a website for accessibility&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>wcag</category>
    </item>
    <item>
      <title>What Is Web Accessibility? Definition and Why It Matters</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Mon, 14 Sep 2026 19:23:01 +0000</pubDate>
      <link>https://dev.to/chille87/what-is-web-accessibility-definition-and-why-it-matters-339b</link>
      <guid>https://dev.to/chille87/what-is-web-accessibility-definition-and-why-it-matters-339b</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://getaccessguard.com/posts/what-is-web-accessibility-and-why-it-matters" rel="noopener noreferrer"&gt;AccessGuard&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;The web was built for everyone&lt;/h2&gt;

&lt;p&gt;When Tim Berners-Lee created the World Wide Web, he envisioned a universal space: &lt;em&gt;"The power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yet today, the vast majority of websites fail to meet basic accessibility standards. A &lt;a href="https://webaim.org/projects/million/" rel="noopener noreferrer"&gt;2026 WebAIM Million&lt;/a&gt; found that 95.9% of the top one million home pages had detected WCAG 2 failures - meaning almost every site on the internet creates barriers for people with disabilities.&lt;/p&gt;

&lt;p&gt;Web accessibility is the practice of designing and developing websites so that people with disabilities can perceive, understand, navigate, and interact with them. But it goes far beyond compliance checkboxes - it's about building a web that works for &lt;strong&gt;everyone&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Accessibility benefits more people than you think&lt;/h2&gt;

&lt;p&gt;When most people hear "accessibility," they think of screen readers and wheelchair ramps. But the reality is much broader. Accessibility improvements help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;People with permanent disabilities&lt;/strong&gt; - including visual, auditory, motor, and cognitive impairments affecting over 1.3 billion people worldwide&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;People with temporary impairments&lt;/strong&gt; - a broken arm, an eye infection, or recovering from surgery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;People in situational limitations&lt;/strong&gt; - using a phone in bright sunlight, watching a video in a noisy café without headphones, or navigating with one hand while holding a child&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aging populations&lt;/strong&gt; - declining vision, hearing, motor control, and memory affect most people as they age&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;People with slow connections&lt;/strong&gt; - accessible sites tend to be lighter and more performant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Microsoft's inclusive design framework estimates that for every person with a permanent disability, there are many more with temporary or situational impairments who benefit from the same design solutions. A captioned video helps someone who is deaf, someone in a loud airport, and someone learning a new language.&lt;/p&gt;

&lt;h2&gt;The legal landscape is tightening&lt;/h2&gt;

&lt;p&gt;Accessibility isn't just good practice - it's increasingly a legal requirement. Here's what you need to know:&lt;/p&gt;

&lt;h3&gt;United States: ADA and Section 508&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Americans with Disabilities Act (ADA)&lt;/strong&gt; has been consistently interpreted by courts to apply to websites. The Department of Justice's &lt;a href="https://www.ada.gov/resources/web-guidance/" rel="noopener noreferrer"&gt;guidance on web accessibility and the ADA&lt;/a&gt; says the ADA's requirements apply to the web services of state and local governments and of businesses open to the public. ADA-related web accessibility lawsuits have surged, with thousands filed each year targeting businesses of all sizes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 508&lt;/strong&gt; requires federal agencies and their contractors to make electronic and information technology accessible. If you do business with the U.S. government, compliance is mandatory.&lt;/p&gt;

&lt;h3&gt;European Union: European Accessibility Act&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;a href="https://commission.europa.eu/strategy-and-policy/policies/justice-and-fundamental-rights/disability/union-equality-strategy-rights-persons-disabilities-2021-2030/european-accessibility-act_en" rel="noopener noreferrer"&gt;European Accessibility Act (EAA)&lt;/a&gt;&lt;/strong&gt;, which has applied to products and services placed on the market since 28 June 2025, requires a wide range of products and services - including e-commerce, banking, and media - to be accessible. It applies to businesses selling to EU consumers, regardless of where the business is based.&lt;/p&gt;

&lt;h3&gt;Beyond these: A global trend&lt;/h3&gt;

&lt;p&gt;Canada (ACA), the UK (Equality Act), Australia (DDA), and dozens of other countries have accessibility laws on the books. The global direction is clear: web accessibility is becoming a legal baseline, not a nice-to-have.&lt;/p&gt;

&lt;h2&gt;The business case for accessibility&lt;/h2&gt;

&lt;p&gt;Even setting aside legal risk, accessibility makes good business sense:&lt;/p&gt;

&lt;h3&gt;Reach a larger audience&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://www.who.int/news-room/fact-sheets/detail/disability-and-health" rel="noopener noreferrer"&gt;World Health Organization&lt;/a&gt; estimates that 1.3 billion people, 16% of the world's population or one in six of us, experience significant disability. That's a market segment larger than any single country except China or India. An inaccessible website simply locks out potential customers.&lt;/p&gt;

&lt;h3&gt;Improve SEO&lt;/h3&gt;

&lt;p&gt;Accessibility and SEO share significant overlap. Proper heading hierarchy, descriptive alt text, semantic HTML, clear link text, and well-structured content all help search engines understand your pages. Google has explicitly stated that many accessibility best practices improve search rankings.&lt;/p&gt;

&lt;h3&gt;Reduce legal risk&lt;/h3&gt;

&lt;p&gt;Defending an accessibility complaint costs money and time that fixing the site up front does not. The failures that end up in a complaint are usually the ones an audit would have listed first, which is the practical argument: the order of the work matters more than any settlement figure.&lt;/p&gt;

&lt;h3&gt;Build brand trust&lt;/h3&gt;

&lt;p&gt;Consumers increasingly care about inclusivity. Demonstrating a commitment to accessibility signals that your brand values all of its customers - a powerful differentiator in competitive markets.&lt;/p&gt;

&lt;h2&gt;Five quick wins to improve accessibility today&lt;/h2&gt;

&lt;p&gt;You don't need to overhaul your entire site overnight. Start with these high-impact changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add alt text to all images.&lt;/strong&gt; Every informational image should have a concise, descriptive alt attribute. Decorative images should have an empty alt (&lt;code&gt;alt=""&lt;/code&gt;) so screen readers skip them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check your color contrast.&lt;/strong&gt; Text should have a contrast ratio of at least 4.5:1 against its background (3:1 for large text). Use a contrast checker tool to verify.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use proper heading hierarchy.&lt;/strong&gt; Start with a single &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, followed by &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;, and so on. Never skip heading levels for styling purposes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Label all form fields.&lt;/strong&gt; Every input needs an associated &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; element. Placeholder text is not a substitute for labels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test with your keyboard.&lt;/strong&gt; Navigate your entire site using only the Tab, Enter, and Arrow keys. Can you reach every interactive element? Can you always see where the focus is?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;How AccessGuard helps&lt;/h2&gt;

&lt;p&gt;Finding accessibility issues by hand is slow and easy to get wrong. AccessGuard runs automated WCAG 2.2 AA checks in a real browser and groups what it finds by category: &lt;a href="https://getaccessguard.com/checks/color-contrast" rel="noopener noreferrer"&gt;color contrast&lt;/a&gt;, &lt;a href="https://getaccessguard.com/checks/alt-text" rel="noopener noreferrer"&gt;alt text&lt;/a&gt;, ARIA attributes, keyboard and focus, headings, forms and more.&lt;/p&gt;

&lt;p&gt;Each issue names the WCAG success criterion behind it and its severity, and paid plans add AI-written fixes, so a team can act on the list without being accessibility experts first. Automated checks find many problems but cannot confirm conformance, so the keyboard and screen reader passes still belong to a person.&lt;/p&gt;

&lt;p&gt;Accessibility is a practice, not a destination. The first step is knowing where a site stands, so run a &lt;a href="https://getaccessguard.com/scan" rel="noopener noreferrer"&gt;free accessibility scan&lt;/a&gt; of one representative page, then read &lt;a href="https://getaccessguard.com/posts/understanding-wcag-the-standard-behind-accessible-websites" rel="noopener noreferrer"&gt;the guide to WCAG&lt;/a&gt; for what the standard asks of you and &lt;a href="https://getaccessguard.com/posts/how-to-audit-your-website-for-accessibility" rel="noopener noreferrer"&gt;the audit checklist&lt;/a&gt; for the manual pass.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>wcag</category>
    </item>
    <item>
      <title>Accessibility Overlays Won't Save You From an ADA Lawsuit</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Mon, 06 Jul 2026 15:13:52 +0000</pubDate>
      <link>https://dev.to/chille87/accessibility-overlays-wont-save-you-from-an-ada-lawsuit-3l78</link>
      <guid>https://dev.to/chille87/accessibility-overlays-wont-save-you-from-an-ada-lawsuit-3l78</guid>
      <description>&lt;p&gt;If your accessibility strategy is "we added the widget," here's a stat worth sitting with: 22.64% of 2025 ADA website lawsuits — 456 cases — targeted sites that already had an accessibility overlay installed. Paying for the tool didn't stop the demand letter.&lt;/p&gt;

&lt;p&gt;This post digs into why: what overlays actually do at the code level (patch the rendered DOM after the page loads), why that timing means screen readers and plaintiffs' scans often never see the patch, and the FTC's April 2025 order that put a $1M fine and a 20-year restriction on one overlay vendor's compliance claims.&lt;/p&gt;

&lt;p&gt;There's a code comparison showing the real difference between a div an overlay tries to patch into a fake button, and an actual &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element that's accessible by default — plus what we've found actually moves the needle on legal exposure: fixing violations in your source HTML, prioritized by which ones show up most often in real lawsuits.&lt;/p&gt;

&lt;p&gt;Full post (cross-posted from the AccessGuard blog) → &lt;a href="https://getaccessguard.com/posts/accessibility-overlays-lawsuit-risk" rel="noopener noreferrer"&gt;https://getaccessguard.com/posts/accessibility-overlays-lawsuit-risk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>Accordions vs Tabs: Why These Two ARIA Patterns Are Not Interchangeable</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Mon, 29 Jun 2026 06:16:58 +0000</pubDate>
      <link>https://dev.to/chille87/accordions-vs-tabs-why-these-two-aria-patterns-are-not-interchangeable-97o</link>
      <guid>https://dev.to/chille87/accordions-vs-tabs-why-these-two-aria-patterns-are-not-interchangeable-97o</guid>
      <description>&lt;p&gt;Most component libraries implement accordions and tabs the same way. They shouldn't.&lt;/p&gt;

&lt;p&gt;Both patterns show a trigger and a panel of content. But the keyboard contract, ARIA roles and screen reader behavior are completely different for each — and mixing them up is one of the most common accessibility bugs I see in audits.&lt;/p&gt;

&lt;p&gt;Here's the short version:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accordions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple panels can be open at once&lt;/li&gt;
&lt;li&gt;Tab key focuses each trigger, Enter/Space toggles it&lt;/li&gt;
&lt;li&gt;Native &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;/&lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; handles this with zero JavaScript&lt;/li&gt;
&lt;li&gt;Full ARIA fallback: &lt;code&gt;&amp;lt;button aria-expanded&amp;gt;&lt;/code&gt; inside a heading + &lt;code&gt;aria-controls&lt;/code&gt; pointing to &lt;code&gt;role="region"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tabs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only one panel visible at a time&lt;/li&gt;
&lt;li&gt;Arrow keys navigate between tabs — NOT the Tab key&lt;/li&gt;
&lt;li&gt;Every inactive tab needs &lt;code&gt;tabindex="-1"&lt;/code&gt; (roving tabindex) or keyboard users get stuck&lt;/li&gt;
&lt;li&gt;ARIA: &lt;code&gt;role="tablist"&lt;/code&gt; &amp;gt; &lt;code&gt;role="tab"&lt;/code&gt; + &lt;code&gt;aria-selected&lt;/code&gt; &amp;gt; &lt;code&gt;role="tabpanel"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wire up the wrong keyboard pattern and keyboard users either can't access the content or have to fight through the component to get there.&lt;/p&gt;

&lt;p&gt;I wrote the full breakdown — with the broken markup and the correct fix for each pattern — on the AccessGuard blog:&lt;/p&gt;

&lt;p&gt;→ &lt;a href="https://getaccessguard.com/posts/accessible-accordions-and-tabs-two-patterns-everyone-confuses" rel="noopener noreferrer"&gt;Accessible Accordions and Tabs: ARIA + Keyboard Patterns&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It covers the exact WCAG criteria, when to use each pattern and which attributes most implementations get wrong. Happy to discuss any of it in the comments.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>aria</category>
      <category>wcag</category>
    </item>
    <item>
      <title>Accessible Accordions and Tabs: The Two Patterns Everyone Confuses</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Thu, 30 Apr 2026 07:35:54 +0000</pubDate>
      <link>https://dev.to/chille87/accessible-accordions-and-tabs-the-two-patterns-everyone-confuses-1eda</link>
      <guid>https://dev.to/chille87/accessible-accordions-and-tabs-the-two-patterns-everyone-confuses-1eda</guid>
      <description>&lt;p&gt;Accordions and tabs look almost identical when you squint, but they're not the same pattern. Different ARIA roles, different keyboard contracts, different reasons to exist — and one of the fastest ways to ship a broken component is to build one with the rules for the other.&lt;/p&gt;

&lt;p&gt;I wrote up the full breakdown on the AccessGuard blog: how to pick the right pattern, the WCAG criteria each one touches, the exact markup that makes them accessible, and the bugs that show up most often in real-world scans.&lt;/p&gt;

&lt;p&gt;Read the full post here 👉 &lt;a href="https://getaccessguard.com/posts/accessible-accordions-and-tabs-two-patterns-everyone-confuses" rel="noopener noreferrer"&gt;https://getaccessguard.com/posts/accessible-accordions-and-tabs-two-patterns-everyone-confuses&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quick teaser of what's covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When to use an accordion vs a tabset (it's structural, not visual)&lt;/li&gt;
&lt;li&gt;Accordion: real &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; inside a real heading, &lt;code&gt;aria-expanded&lt;/code&gt;, &lt;code&gt;aria-controls&lt;/code&gt;, and the &lt;code&gt;hidden&lt;/code&gt; attribute&lt;/li&gt;
&lt;li&gt;Tabset: &lt;code&gt;role="tab"&lt;/code&gt;, roving &lt;code&gt;tabindex&lt;/code&gt;, and the Arrow / Home / End keyboard model that nothing else on the web uses&lt;/li&gt;
&lt;li&gt;Why mobile "tabset that collapses into an accordion" needs a markup swap, not just a CSS swap&lt;/li&gt;
&lt;li&gt;A 5-minute keyboard test you can run before shipping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you maintain a component library or you're about to reach for an accordion in your next sprint, this one's for you.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>html</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Build Accessible Custom Dropdowns (Comboboxes) That Actually Work</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Thu, 23 Apr 2026 09:20:57 +0000</pubDate>
      <link>https://dev.to/chille87/how-to-build-accessible-custom-dropdowns-comboboxes-that-actually-work-16bo</link>
      <guid>https://dev.to/chille87/how-to-build-accessible-custom-dropdowns-comboboxes-that-actually-work-16bo</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://getaccessguard.com/posts/how-to-build-accessible-custom-dropdowns-comboboxes-that-actually-work" rel="noopener noreferrer"&gt;AccessGuard blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After our post on accessible modals resonated with so many of you, we wanted to tackle another notoriously tricky pattern: the custom dropdown, or combobox. Native &lt;code&gt;select&lt;/code&gt; elements are accessible out of the box, but the moment you need custom styling, searchable options, multi-select, or grouped items, you end up reimplementing a lot of browser behavior — and that is where accessibility usually breaks.&lt;/p&gt;

&lt;p&gt;This post walks through the pieces you need to get right: semantics, keyboard support, focus management, and announcements. By the end you will have a mental checklist you can apply to any dropdown in your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Start with the right roles
&lt;/h2&gt;

&lt;p&gt;A combobox is not just a styled button. The WAI-ARIA Authoring Practices define a specific role structure: a combobox element (usually a button or input) with &lt;code&gt;aria-haspopup="listbox"&lt;/code&gt;, &lt;code&gt;aria-expanded&lt;/code&gt; reflecting open state, and &lt;code&gt;aria-controls&lt;/code&gt; pointing to the listbox id. The popup itself uses &lt;code&gt;role="listbox"&lt;/code&gt; and each option uses &lt;code&gt;role="option"&lt;/code&gt; with &lt;code&gt;aria-selected&lt;/code&gt; on the active option. If you only remember one thing: roles must match behavior. Do not slap &lt;code&gt;role="listbox"&lt;/code&gt; on a div that behaves like a menu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Make the trigger reachable and descriptive
&lt;/h2&gt;

&lt;p&gt;The trigger must be a real focusable element — either a native button or an input with &lt;code&gt;tabindex="0"&lt;/code&gt;. Give it an accessible name using a visible label, &lt;code&gt;aria-label&lt;/code&gt;, or &lt;code&gt;aria-labelledby&lt;/code&gt;. Announce the current value so screen reader users hear "Country, combobox, United States" and not just "combobox, collapsed."&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Keyboard support is non-negotiable
&lt;/h2&gt;

&lt;p&gt;This is where most custom dropdowns fail. At a minimum you need: Enter or Space to open the listbox, Arrow Down to open and move to the first or selected option, Arrow Up and Arrow Down to move between options, Home and End to jump to the first and last option, Escape to close and return focus to the trigger, Tab to close and move to the next focusable element, and typeahead so pressing a letter jumps to the next matching option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Manage focus, not just visual highlight
&lt;/h2&gt;

&lt;p&gt;Here is the subtle part. In a listbox pattern, DOM focus stays on the combobox trigger. You do not move focus into the list. Instead, you track the active option with &lt;code&gt;aria-activedescendant&lt;/code&gt;, pointing at the id of the currently highlighted option. This keeps typeahead and keyboard handlers on the trigger while still telling assistive tech which option is active. Moving real focus into the list is a common mistake that breaks typeahead and confuses screen readers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Announce changes without being noisy
&lt;/h2&gt;

&lt;p&gt;When the listbox opens, screen readers should announce the expanded state and the active option. You get this for free if &lt;code&gt;aria-expanded&lt;/code&gt; and &lt;code&gt;aria-activedescendant&lt;/code&gt; are wired up correctly. Avoid adding extra &lt;code&gt;aria-live&lt;/code&gt; regions that duplicate this — double announcements are worse than none.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Do not forget the close behaviors
&lt;/h2&gt;

&lt;p&gt;Close the listbox on Escape, on outside click, and on blur of the combobox. When closing via Escape, restore focus to the trigger. When a user selects an option, update the trigger's visible text and its accessible name, close the listbox, and return focus to the trigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick testing checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Can you open, navigate, select, and close using only the keyboard?&lt;/li&gt;
&lt;li&gt;Does VoiceOver or NVDA announce the role, state, and active option?&lt;/li&gt;
&lt;li&gt;Does typeahead work?&lt;/li&gt;
&lt;li&gt;Does Escape always return focus to the trigger?&lt;/li&gt;
&lt;li&gt;Do touch users on mobile get a usable experience? (hint: test with TalkBack and VoiceOver on iOS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you can answer yes to all of these, you are ahead of 90% of the custom dropdowns on the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to skip all of this
&lt;/h2&gt;

&lt;p&gt;Honestly? Use the native &lt;code&gt;select&lt;/code&gt; element whenever you can. It is accessible, it works on every platform, and mobile browsers give you a great picker for free. Only build a custom combobox when you genuinely need features native select cannot provide — searchable options, rich option content, or async loading. The best accessible component is often the one you did not have to build.&lt;/p&gt;




&lt;p&gt;We will follow this up with a post on accessible autocompletes, which add another layer of complexity on top of this pattern. If there is a tricky component you would like us to cover next, let us know.&lt;/p&gt;

&lt;p&gt;Read more from AccessGuard at &lt;a href="https://getaccessguard.com/posts" rel="noopener noreferrer"&gt;getaccessguard.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>javascript</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Sat, 18 Apr 2026 21:30:06 +0000</pubDate>
      <link>https://dev.to/chille87/-leh</link>
      <guid>https://dev.to/chille87/-leh</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/chille87/im-building-a-flat-priced-alternative-to-churnkey-for-saas-doing-3k-30k-mrr-fp3" class="crayons-story__hidden-navigation-link"&gt;I'm building a flat-priced alternative to Churnkey for SaaS doing $3k-$30k MRR&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/chille87" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3016792%2F2823df19-1334-438f-a4ad-f592800a3f19.jpg" alt="chille87 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/chille87" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Denis Omerovic
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Denis Omerovic
                
              
              &lt;div id="story-author-preview-content-3520717" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/chille87" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3016792%2F2823df19-1334-438f-a4ad-f592800a3f19.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Denis Omerovic&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/chille87/im-building-a-flat-priced-alternative-to-churnkey-for-saas-doing-3k-30k-mrr-fp3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/chille87/im-building-a-flat-priced-alternative-to-churnkey-for-saas-doing-3k-30k-mrr-fp3" id="article-link-3520717"&gt;
          I'm building a flat-priced alternative to Churnkey for SaaS doing $3k-$30k MRR
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/saas"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;saas&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/buildinpublic"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;buildinpublic&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/indiehackers"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;indiehackers&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/startup"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;startup&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/chille87/im-building-a-flat-priced-alternative-to-churnkey-for-saas-doing-3k-30k-mrr-fp3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>I'm building a flat-priced alternative to Churnkey for SaaS doing $3k-$30k MRR</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Sat, 18 Apr 2026 21:29:34 +0000</pubDate>
      <link>https://dev.to/chille87/im-building-a-flat-priced-alternative-to-churnkey-for-saas-doing-3k-30k-mrr-fp3</link>
      <guid>https://dev.to/chille87/im-building-a-flat-priced-alternative-to-churnkey-for-saas-doing-3k-30k-mrr-fp3</guid>
      <description>&lt;h2&gt;
  
  
  The problem, with real numbers
&lt;/h2&gt;

&lt;p&gt;If you run a Stripe-native SaaS between roughly $3k and $30k MRR, somewhere between 5% and 10% of your monthly revenue quietly disappears to failed cards. Expired cards, insufficient funds, the usual. On $10k MRR that's $500-$1,000 a month walking out the door before you even notice.&lt;/p&gt;

&lt;p&gt;The fix is known: smarter retries based on the decline code, plus a hosted page where the customer can update their card in 30 seconds. That second piece recovers more than retry timing ever will.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the existing options don't fit this band
&lt;/h2&gt;

&lt;p&gt;Churnkey is genuinely good, but the floor is about $3k a year and they take 1-3% of every recovered dollar on top. That math only works once you're past $30k MRR. Stunning is cheaper but the UX feels frozen in 2017 and the config is scattered. ProfitWell Retain killed its free tier. Baremetrics Recover has been coasting for years. If you're below $30k MRR you basically write your own retry cron job and hope.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm building
&lt;/h2&gt;

&lt;p&gt;Nanokept. Flat pricing: $49, $149, or $349 a month by your MRR band. Never a percent of recovered revenue.&lt;/p&gt;

&lt;p&gt;What's in the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stripe Connect OAuth install, read-only, about 90 seconds&lt;/li&gt;
&lt;li&gt;Decline-code-aware retries: soft declines retry on day 1/3/5/7/14, hard declines stop auto-retrying and trigger a branded customer email&lt;/li&gt;
&lt;li&gt;Hosted card-update page per failed invoice&lt;/li&gt;
&lt;li&gt;Idempotency keys on every Invoice.pay call so a network hiccup never double-charges anyone&lt;/li&gt;
&lt;li&gt;Works against the Stripe sandbox from day one, which I was surprised to find most competitors still don't&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rails 8, SolidQueue for the retry jobs, EU-hosted on Hetzner with Cloudflare in front. I'm solo, based in Bosnia, and billing through Lemon Squeezy as merchant of record since I can't take Stripe directly from here. Previous project was AccessGuard (getaccessguard.com).&lt;/p&gt;

&lt;h2&gt;
  
  
  Status
&lt;/h2&gt;

&lt;p&gt;Landing page and waitlist are live at nanokept.com. Product is mid-build, targeting end of May 2026 for the first paying cohort.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd like from you
&lt;/h2&gt;

&lt;p&gt;Two questions for anyone running a Stripe SaaS in this MRR band:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What's your actual recovery rate right now, and do you even measure it?&lt;/li&gt;
&lt;li&gt;If you've looked at dunning tools and bounced off them, what was the dealbreaker: the price floor, the revenue share, the setup time, or something else?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Link: &lt;a href="https://nanokept.com" rel="noopener noreferrer"&gt;https://nanokept.com&lt;/a&gt;. Happy to answer anything in the comments.&lt;/p&gt;

</description>
      <category>saas</category>
      <category>buildinpublic</category>
      <category>indiehackers</category>
      <category>startup</category>
    </item>
    <item>
      <title>6 Accessibility Checks Most Scanners Miss (And How AccessGuard Catches Them)</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Thu, 16 Apr 2026 20:54:14 +0000</pubDate>
      <link>https://dev.to/chille87/6-accessibility-checks-most-scanners-miss-and-how-accessguard-catches-them-2gcf</link>
      <guid>https://dev.to/chille87/6-accessibility-checks-most-scanners-miss-and-how-accessguard-catches-them-2gcf</guid>
      <description>&lt;p&gt;axe, WAVE, Lighthouse, Pa11y, and Siteimprove share a rules-engine lineage and share its soft spots. Here are six checks where that baseline tends to under-report, over-report, or punt to manual review, with notes on how we approached each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where scanners agree, and where they stop
&lt;/h2&gt;

&lt;p&gt;Most popular accessibility scanners share a foundation — either axe-core directly or a similar rules engine that reads the static HTML. That gives them fast, reliable coverage of the obvious issues: missing alt text, empty links, heading order, deterministic ARIA misuse. It also means they all share the same blind spots.&lt;/p&gt;

&lt;p&gt;We audited what slips through, then built detection for six of the most common gaps. This post walks through each one, explains why it is hard, and shows what a real fix looks like. If you are using any of the major scanners, use this as a checklist for what to double-check by hand.&lt;/p&gt;

&lt;p&gt;Run the same page through axe-core, WAVE, Lighthouse, Pa11y, and Siteimprove and you will get broadly similar results for the deterministic rules. That is not a bad thing — the shared baseline catches real problems and catches them fast. What the shared baseline does not catch is anything that requires one of three things: actual browser behavior (not just the DOM), computed state that is not expressed in HTML attributes, or visual geometry that only exists after layout. That is where every scanner has gaps, and it is where we focused this round of work.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. onclick handlers attached through JavaScript (2.1.1 Keyboard)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; A common pattern in React, Vue, Svelte, and vanilla JS apps: a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with a click handler attached via &lt;code&gt;addEventListener&lt;/code&gt;. The HTML looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt; &lt;span class="na"&gt;data-id=&lt;/span&gt;&lt;span class="s"&gt;"42"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Open&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;code&gt;onclick&lt;/code&gt; attribute, no role, no tabindex — but in the browser, clicking it runs a handler and so does pressing Enter (if the framework wired up a keydown listener too).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why static scanners miss it:&lt;/strong&gt; axe, WAVE, and the rest read the HTML as it arrives from the DOM. They can see &lt;code&gt;onclick="..."&lt;/code&gt; as an inline attribute, but they cannot see listeners attached with &lt;code&gt;element.addEventListener("click", ...)&lt;/code&gt; because those live in JavaScript state, not the attribute set. So they either miss the problem entirely (no flag on a mouse-only div) or over-report (flag every div with a keydown-less onclick even when the framework attached a keydown listener dynamically).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we do:&lt;/strong&gt; Before the page script runs, we inject a small shim that wraps &lt;code&gt;EventTarget.prototype.addEventListener&lt;/code&gt;. Every call to attach a &lt;code&gt;click&lt;/code&gt;, &lt;code&gt;keydown&lt;/code&gt;, &lt;code&gt;keyup&lt;/code&gt;, or &lt;code&gt;keypress&lt;/code&gt; handler gets recorded in a WeakMap keyed by the target element. After the page finishes loading, we query that map and tell the scanner which elements actually received keyboard handlers. The onclick-without-keyboard warning only fires on elements that truly have no keyboard path.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pseudo-element text contrast (1.4.3 Contrast)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; CSS &lt;code&gt;::before&lt;/code&gt; and &lt;code&gt;::after&lt;/code&gt; with a &lt;code&gt;content&lt;/code&gt; property render real text to the screen, and that text is subject to the same contrast requirements as any other text. Examples: icon labels, counter numbers, status badges, the "Required" asterisk on form labels.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.badge&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"New"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e0e0e0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is 1.13:1 contrast. Invisible. A screen reader will not read it, but the visible rendering still fails WCAG 1.4.3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why static scanners miss it:&lt;/strong&gt; axe-core has attempted pseudo-element contrast since 2022, but the implementation has documented gaps: pseudo-elements without &lt;code&gt;position: absolute&lt;/code&gt; are frequently missed, and icon-style pseudo-elements often produce false positives that teams waive. WAVE, Lighthouse (which uses axe), and Pa11y inherit the same behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we do:&lt;/strong&gt; While we are in the browser computing styles for every element, we also call &lt;code&gt;getComputedStyle(el, "::before")&lt;/code&gt; and &lt;code&gt;getComputedStyle(el, "::after")&lt;/code&gt;. If the resulting content is a non-empty string literal, we capture the pseudo-element's color, background, and font size as a separate entry. The contrast checker then evaluates those entries with the same logic it uses for real elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Contrast over transparent backgrounds and background images (1.4.3 Contrast)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; Modern layouts use transparent backgrounds constantly. A card inside a section inside the body. A header overlay on a hero image. A navigation bar with a semi-transparent background.&lt;/p&gt;

&lt;p&gt;axe-core walks the element stack using &lt;code&gt;document.elementsFromPoint&lt;/code&gt; to find the effective background, but the approach has documented edge cases: translucent overlays on modals are included incorrectly, opacity on ancestors is handled inconsistently, and when the effective background is a gradient or image the check either errors out or flags it as needs-review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this is hard:&lt;/strong&gt; There is no single correct answer. The "real" background behind transparent text is whatever happens to be rendered at that pixel, which depends on layout, scroll position, and z-order. For images and gradients, contrast varies across the image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we do:&lt;/strong&gt; For transparent backgrounds, we walk up the DOM tree until we find an ancestor with a non-transparent background color. Between 98% and 100% of pages have a reachable opaque ancestor. For background images or gradients, we emit an honest notice instead of pretending we know the answer — the notice tells you the element sits over a background image and that contrast cannot be reliably computed, with a suggestion to verify manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Real 320px reflow at an actual viewport (1.4.10 Reflow)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; WCAG 1.4.10 requires content to reflow to 320 CSS pixels without horizontal scrolling. The usual offenders: fixed-width containers, &lt;code&gt;min-width&lt;/code&gt; greater than 320px, tables with no responsive wrapper, wide images without &lt;code&gt;max-width: 100%&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why static checks fall short:&lt;/strong&gt; You can write static heuristics — look for inline &lt;code&gt;width: 1200px&lt;/code&gt;, flag &lt;code&gt;overflow-x: scroll&lt;/code&gt; on the body. But a lot of reflow failures only manifest when you actually narrow the viewport: a grid that does not collapse, a flex row that does not wrap, content hidden inside a wrapper whose child has a fixed aspect ratio that exceeds the viewport.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we do:&lt;/strong&gt; We run a second browser pass at 320x640 after the main scan. The viewport is resized, layout re-runs, and we query &lt;code&gt;document.documentElement.scrollWidth&lt;/code&gt; versus &lt;code&gt;clientWidth&lt;/code&gt;. If the page requires horizontal scrolling at 320px, it fails 1.4.10. We also enumerate the first 20 elements whose &lt;code&gt;getBoundingClientRect().right&lt;/code&gt; exceeds 320px, so you know exactly which containers are the culprits.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Sectioning-aware heading hierarchy (1.3.1 Info and Relationships)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; WCAG 1.3.1 requires a logical heading hierarchy. In practice, scanners flag "skipped heading levels" whenever the next heading is more than one level below the previous one — h1 followed by h3, for example. That rule is correct at the document level. It is wrong inside sectioning content. A page that has an &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; with its own &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, or a card layout with independent heading outlines, is following the HTML5 sectioning spec. Flagging every one of those produces 10 to 30 false positives on any page with multiple articles, sidebars, or modal dialogs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why most scanners get this wrong:&lt;/strong&gt; A flat walk over all headings is easy to write. Tracking sectioning context is harder, so most engines do not bother. axe-core does not reset hierarchy at sectioning boundaries. Neither does WAVE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we do:&lt;/strong&gt; We group headings by their nearest sectioning ancestor — &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt;, &lt;code&gt;role="article"&lt;/code&gt;, &lt;code&gt;role="region"&lt;/code&gt; — before running the hierarchy check. Each sectioning root gets its own starting heading level, and skips are evaluated within that scope. We also filter out hidden headings so invisible elements do not pollute the hierarchy.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Framework-aware severity (2.1.1 Keyboard)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; An onclick handler on a plain &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; without any keyboard path is a real bug. An onclick handler on a &lt;code&gt;&amp;lt;div role="button" tabindex="0"&amp;gt;&lt;/code&gt; probably is not — that is a standard pattern where the framework has wired up Enter and Space key handlers. Most scanners give both cases the same severity. You end up with a dashboard full of "errors" that are often framework false positives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we do:&lt;/strong&gt; Severity depends on signal strength. If a div has &lt;code&gt;role="button"&lt;/code&gt;, it is already announced as interactive — we skip it. If a div has &lt;code&gt;tabindex="0"&lt;/code&gt; and an onclick but no explicit keyboard handler, we demote it from error to notice. If neither role nor tabindex is present, we keep it as a warning because we genuinely cannot be sure there is no keyboard path. Combined with the addEventListener tracking from item 1, the false-positive rate on this specific check drops close to zero on modern framework sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with this
&lt;/h2&gt;

&lt;p&gt;If you are evaluating accessibility scanners, ask the vendor how they handle each of the six cases above. Not because those are the only things that matter — most scanners cover the deterministic baseline, and they all matter more than these edge cases — but because how a vendor answers tells you how seriously they have thought about the long tail of real-world accessibility.&lt;/p&gt;

&lt;p&gt;If you are just trying to make your own site accessible, the short version is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run any scanner. The shared baseline catches most real issues.&lt;/li&gt;
&lt;li&gt;Hand-check the categories above on a few representative pages, especially if you use a modern JS framework, CSS pseudo-elements, or card-heavy layouts.&lt;/li&gt;
&lt;li&gt;Treat scanner notices as signals to investigate, not as failures. Especially for 1.4.3 (contrast) and 1.4.10 (reflow), the "unknown" cases are often where real problems hide.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://getaccessguard.com/posts/6-accessibility-checks-most-scanners-miss-and-how-accessguard-catches-them" rel="noopener noreferrer"&gt;the AccessGuard blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Accessibility Lawsuits Surged 27% in 2025. Here's Why Developers Should Care About 2026.</title>
      <dc:creator>Denis Omerovic</dc:creator>
      <pubDate>Wed, 15 Apr 2026 20:26:35 +0000</pubDate>
      <link>https://dev.to/chille87/accessibility-lawsuits-surged-27-in-2025-heres-why-developers-should-care-about-2026-3n7h</link>
      <guid>https://dev.to/chille87/accessibility-lawsuits-surged-27-in-2025-heres-why-developers-should-care-about-2026-3n7h</guid>
      <description>&lt;p&gt;Federal courts saw &lt;strong&gt;3,117 website accessibility lawsuits&lt;/strong&gt; in 2025 — a 27% jump from 2024. That spike wiped out two years of decline, and 69% of those lawsuits targeted e-commerce businesses.&lt;/p&gt;

&lt;p&gt;If you're building websites or web apps, this matters. Here's what's driving the surge and why 2026 will be even worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Is Making It Ridiculously Easy to Sue
&lt;/h2&gt;

&lt;p&gt;40% of federal ADA Title III filings in 2025 came from &lt;strong&gt;pro se plaintiffs&lt;/strong&gt; — people filing lawsuits without a lawyer. AI tools now let someone generate a legal complaint in minutes. No $5,000 retainer. No attorney consultations.&lt;/p&gt;

&lt;p&gt;Plaintiff's law firms are also using AI to scan hundreds of websites at once, flagging accessibility violations automatically, then filing batches of complaints.&lt;/p&gt;

&lt;h2&gt;
  
  
  The European Accessibility Act Is Now Live
&lt;/h2&gt;

&lt;p&gt;The EAA took effect on June 28, 2025 across all 27 EU member states. Penalties vary but they're painful — up to &lt;strong&gt;€100,000 per violation&lt;/strong&gt; in Germany and Italy, and up to 4% of annual revenue in France.&lt;/p&gt;

&lt;p&gt;If your site has EU customers, the EAA applies to you regardless of where your business is based. Unlike the ADA, the EAA &lt;strong&gt;explicitly requires WCAG compliance&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The April 2026 Title II Deadline Changes Everything
&lt;/h2&gt;

&lt;p&gt;The new ADA Title II web accessibility rule solidifies &lt;strong&gt;WCAG 2.1 Level AA&lt;/strong&gt; as the benchmark courts reference. This makes it easier for plaintiffs to argue their case against &lt;em&gt;any&lt;/em&gt; business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overlays Won't Save You
&lt;/h2&gt;

&lt;p&gt;25% of all ADA lawsuits in 2024 targeted websites that already had accessibility overlays installed. The FTC reached a &lt;strong&gt;$1 million settlement&lt;/strong&gt; with an overlay provider for misleading compliance claims.&lt;/p&gt;

&lt;p&gt;Overlays don't fix your code. They add a layer on top of broken HTML. Courts aren't buying it, and plaintiff's lawyers specifically look for overlay widgets as targets.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Developers Should Do
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;94.8% of websites&lt;/strong&gt; fail basic accessibility checks. The most common issues are things developers can fix:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Missing alt text on images&lt;/strong&gt; — the #1 issue cited in lawsuits&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broken keyboard navigation&lt;/strong&gt; — dropdowns, modals, and cart flows are common failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Poor color contrast&lt;/strong&gt; — easy to fix, constantly flagged&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing form labels&lt;/strong&gt; — screen reader users can't complete purchases without them&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Accessibility lawsuits jumped 27% last year. AI is making them cheaper to file. The EU is actively enforcing. Overlays are being exposed. Every trend points to more lawsuits, targeting more businesses, in more places.&lt;/p&gt;

&lt;p&gt;If you're a developer, accessibility isn't optional — it's a legal requirement that's getting enforced more aggressively every year.&lt;/p&gt;

&lt;p&gt;Read the full breakdown with all the data: &lt;a href="https://getaccessguard.com/posts/accessibility-lawsuits-surged-27-percent-2025-why-2026-will-be-worse" rel="noopener noreferrer"&gt;Website Accessibility Lawsuits Surged 27% in 2025. Here's Why 2026 Will Be Even Worse.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>a11y</category>
      <category>discuss</category>
      <category>news</category>
    </item>
  </channel>
</rss>
