ChatGPT Accessible HTML

by Lourens — 6 minutes

I've been playing around with ChatGPT at I'm exploring how a tool like this can complement my software development. In this article I'm showing you my findings on ChatGPT's ability to write accessible HTML according to the Web Content Accessibility Guidelines (WCAG).

In a previous article I explored the AI's ability to create basic React components for me. Then I was able to give commands to extend these basic components. From this I learned this tool works best when you take a step-by-step approach. Let's see if I come to the same conclusion again.

I'm going to tell the AI to generate me accessible HTML. Everything it generates I'll run on my localhost and I'll open it in my browser. Then with the WAVE accessibility analysis chrome plugin I'll validate that it's actually somewhat accessible. This plugin is also recommended by W3C in their Web Accessibility training.

Note that if you want to analyse an HTML file in your browser with WAVE, you'll have to serve that HTML file with something like the serve npm package.

Me: make me an accessible html contact form


  <label for="name">Name:</label><br />
  <input type="text" id="name" name="name" required /><br />
  <label for="email">Email:</label><br />
  <input type="email" id="email" name="email" required /><br />
  <label for="message">Message:</label><br />
  <textarea id="message" name="message" required></textarea><br />
  <button type="submit">Send</button>

This looks good to me. Let's open this in a browser an analyse it with WAVE. The next image will show you the analysis result. As you can see, we're getting 2 errors and 2 alerts.

  1. ERROR: Missing or uninformative page title
  2. ERROR: Language missing or invalid
  3. ALERT: No heading structure
  4. ALERT: No page regions

contact form in browser with WAVE analysis showing 2 errors and 2 alerts

Most of these are caused by having just a loose form element in the DOM. Let's tell the AI to put this in an accessible page and see what happens.

Me: put this form in an accessible page


<!DOCTYPE html>
<html lang="en">
    <title>Contact Us</title>
      <h1>Contact Us</h1>
        <li><a href="#main">Main Content</a></li>
        <li><a href="#form">Contact Form</a></li>
    <main id="main">
      <h2>Contact Information</h2>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua.
      <h2 id="form">Contact Form</h2>
        <label for="name">Name:</label><br />
        <input type="text" id="name" name="name" required /><br />
        <label for="email">Email:</label><br />
        <input type="email" id="email" name="email" required /><br />
        <label for="message">Message:</label><br />
        <textarea id="message" name="message" required></textarea><br />
        <button type="submit">Send</button>
      <p>Copyright 2022</p>

When I open this in my browser and analyse it with WAVE again I no longer get any errors or alerts. That's great, now we know the AI is at least aware of WCAG 2.1.

contact form in browser with WAVE analysis showing no errors or alerts

In 2023 we're getting WCAG 2.2, but this AI is not and probably won't be aware of the world past 2021 for a while. This is a serious limitation to consider when leveraging this tool.

Let's continue though. The AI took the liberty to add a contact information heading and paragraph. I don't want that. Back in the day we would select this part and either press backspace or delete. Now we can tell the AI to do it for us by saying remove the contact information.

I want to see how far I can push the AI to write me accessible HTML. Let's try something like CAPTCHA. A Screen Reader User Survey by WebAIM listed CAPTCHA as the most problematic item causing difficulty and frustration amongst people with disabilities.

Me: create an accessible captcha in html


  <p>Please answer the following question to verify that you are a human:</p>
  <p>What is the capital of France?</p>
  <label for="captcha-answer">Answer:</label>
  <input type="text" id="captcha-answer" />
  <button type="submit">Submit</button>

This is not what I'm looking for. It's accessible, but this is more of a placeholder. I think I'll need to be more specific. Let's try telling it to use Google's reCAPTCHA.

Me: implement Google's reCAPTCHA

Chatbot: To implement Google's reCAPTCHA in an HTML form, you will need to sign up for an API key pair from Google. Once you have the API key pair, you can add the following code to your HTML form:

<form action="..." method="post">
  <div class="g-recaptcha" data-sitekey="your_site_key"></div>
  <script src="" async defer></script>

This is closer to what I want, but still limited. At this point the added value of the chatbot is limited because of the placeholder ...'s and I think it'd be faster for me to just copy paste from the documentation at Let's try this in a React component.

Me: implement recaptcha in a react component


import React from "react";
import ReCAPTCHA from "react-google-recaptcha";

const RecaptchaExample = () => {
  const [value, setValue] = useState(null);

  const onChange = (value) => {

  return <ReCAPTCHA sitekey="your-site-key" onChange={onChange} />;

This works! Apparently ChatGPT is more comfortable with React than it is with plain HTML. That could be explained by the abstractions that a framework like React offers. It was only a matter of importing and rendering a dependency. Let's analyze it in the browser.

Google reCAPTCHA shown in React app in browser with WAVE analysis showing missing form label error

As you can see the only error is about the form label missing. That's apparently an issue in the dependency itself. A textarea element is missing a label. I told the AI to make this accessible a few times. Sometimes it adds a label and sometimes an aria-label to the component as shown be low, but WAVE keeps complaining.

return (
    label="Complete the reCAPTCHA challenge to continue"

This has been my experience each time I mess around with this Chatbot. It starts out promising, but when I get to a point of some complexity (like issues in dependencies or the use of external processes like GCP resources) I start needing to do manual actions instead of letting the AI do it for me.

I suggest you mess around too at and see if you can find proper ways to add this tool to your workflow.