Built your website with an AI builder? 8 accessibility problems to check before launch
Sites made with Lovable, Bolt, v0, Replit or Cursor often ship clickable divs, unnamed icon buttons, placeholder-only fields, pale grey text and one page title for every page. What to check, the code fix, and a prompt to give your builder.
AI builders such as Lovable, Bolt, v0, Replit and Cursor can turn a description into a working website in an afternoon. The pages look finished, but the code underneath often skips the parts people who use a keyboard, a screen reader or zoom rely on. None of these problems are hard to fix once you know where to look. Here are the eight we'd check first, with the fix and a prompt you can paste into your builder.
1. Clickable boxes that aren't real buttons
Generated code sometimes makes a <div> or <span> clickable instead of using a button or link. A mouse works; Tab and Enter don't, and a screen reader doesn't announce it as a button. The W3C's first rule of ARIA is to use the native HTML element when one exists (Using ARIA, and WCAG 4.1.2 Name, Role, Value).
<!-- Mouse-only -->
<div className="cta" onClick={openBooking}>Book now</div>
<!-- Works with mouse, keyboard and screen readers -->
<button type="button" className="cta" onClick={openBooking}>Book now</button>
<a href="/pricing">See pricing</a>Rule of thumb: if it goes somewhere, it's a link; if it does something on the page, it's a button.
2. Icon-only buttons with no name
Menu, close, search, cart and social icons are usually just an SVG. Without a text name they're announced as "button" and nothing else. Give each one a name:
<button type="button" aria-label="Open menu" aria-expanded="false" aria-controls="site-menu"> <svg aria-hidden="true" focusable="false">…</svg> </button>
More in our link and button text guide.
3. Form fields with only placeholder text
Grey placeholder text disappears as soon as someone types, and screen readers may not treat it as a label. Every field needs a visible label tied to it, and errors should be written in words, not just a red border:
<label htmlFor="email">Email</label> <input id="email" type="email" autoComplete="email" required aria-describedby="email-error" /> <p id="email-error">Enter an email address like [email protected]</p>
(React writes htmlFor and autoComplete; plain HTML uses for and autocomplete.) See accessible contact forms.
4. Pale grey text
Light grey body or helper text is a popular look. WCAG 1.4.3 Contrast (Minimum) asks for at least 4.5:1 for normal-size text. As a worked example, the grey #9ca3af on white is about 2.5:1, which fails; #6b7280 on white is about 4.8:1, which passes. Check your own colours with a contrast checker (see our colour contrast guide), and check buttons, links and text on photos too.
5. Focus outlines switched off
A common style reset removes the focus ring (outline: none, or a utility class like outline-none or focus:outline-none) without adding anything back. Keyboard users then can't see where they are, which WCAG 2.4.7 Focus Visible asks you to avoid. Put a clear style back for keyboard focus:
:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 2px; }Then try our 5-minute keyboard test.
6. One page title (and no language) for the whole site
Single-page apps often keep the same <title> on every page, or leave the starter-template title in place, and sometimes drop the page language. Give each page its own title (WCAG 2.4.2 Page Titled), such as "Pricing | Your Business", and set the language on the <html> tag (WCAG 3.1.1):
<html lang="en"> <title>Pricing | Oak Street Dental, Tulsa</title>
7. Headings picked by size, not by order
Generated pages often use H3 or H4 because the text "looked right", or style a plain div as a heading. Use one H1 that says what the page is, then H2s for sections and H3s inside them, and change the size with CSS. See heading structure.
8. Messages and page changes nobody hears
"Message sent", "Added to cart" or a form error that pops up after a click is visible but silent to a screen reader unless it's in a live region (WCAG 4.1.3 Status Messages). When the app moves to a new "page" without a full reload, also move focus to the new page's heading so keyboard and screen reader users start in the right place.
<p role="status">{statusMessage}</p>
Plus: images, alt text and modals
Check that every meaningful image has alt text that says what it shows (try our free alt text checker), decorative ones have alt="", and pop-ups and modals can be closed with Escape and return focus to the button that opened them (pop-up guide). Phones matter too: make sure the viewport tag doesn't block zoom (mobile guide).
A prompt to give your AI builder
Paste this into your builder, then review the changes yourself. AI tools can claim a fix they didn't make, so re-test afterwards.
Review this site for accessibility (WCAG 2.2 AA) and fix, without changing the design: 1. Replace clickable div/span elements with <button> or <a href>. 2. Give every icon-only button and link an aria-label; hide decorative SVGs with aria-hidden="true". 3. Give every form field a visible <label> linked by id; write errors as text linked with aria-describedby. 4. Make all text at least 4.5:1 contrast (3:1 for large text); list any colours you changed. 5. Restore a visible :focus-visible style wherever outlines are removed. 6. Set lang="en" on <html> and a unique, descriptive <title> on every route. 7. Use one H1 per page and headings in order (H2, then H3). 8. Announce status messages with role="status"; move focus to the H1 after route changes. 9. Add meaningful alt text to images (alt="" for decorative ones). 10. Make modals close with Escape and return focus to the button that opened them. List every file and change you made.
A 10-minute check before launch
- Run a free homepage scan.
- Unplug the mouse and Tab through the homepage, menu and contact form. Can you see where you are and use everything?
- Zoom the browser to 200% and open the site on your phone. Does anything get cut off or overlap?
- Open each main page and read the browser tab. Does each page have its own title?
- Submit the contact form empty. Is the error written in words next to the field?
- Listen to the homepage for two minutes with a screen reader (screen reader test).
What a scan can and can't check here
Our scan loads your pages in a real headless Chrome browser, so it checks the page after your app's JavaScript has run, the way visitors see it. Using axe-core it catches unnamed buttons and links, unlabelled fields, contrast it can measure, missing alt text, heading order, missing page language and title, and a viewport tag that blocks zoom. It can't tell whether a clickable div is meant to be a button in every case, whether focus is visible and lands in the right place after a route change, whether messages are announced at the right time, or how pages behind a login work, and it only sees the pages it loads. Automated checks find only part of accessibility barriers, which is why the 10-minute check above matters.
This is general technical guidance, not legal advice, and it does not certify compliance with the ADA or any law.
Want the fixes written for you?
Start with a free homepage snapshot. The $149 Fix-Pack scans up to 10 pages and gives copy-paste fixes for your platform within 48 hours, with a 14-day refund promise. See a sample report first.
This is general technical guidance, not legal advice, and it does not certify compliance with the ADA or any law.
Related guides
- We scanned 10 small-business home pages: the most common accessibility issues (2026)
- WCAG 2.2 explained for small-business websites
- Squarespace accessibility fixes: alt text, contrast, forms and more
- Wix accessibility fixes: a practical checklist
This guide is general technical information, not legal advice. Following it does not certify ADA or any legal compliance. Automated checks find only part of accessibility barriers.
Check your own site
Run a free homepage snapshot to see your top 3 issues in about a minute, or order the $149 Fix-Pack for up to 10 pages with copy-paste fixes for your platform.