{"version":"https://jsonfeed.org/version/1","title":"Aaron Gustafson: Content tagged WAI-ARIA","description":"The latest 20 posts and links tagged WAI-ARIA.","home_page_url":"https://www.aaron-gustafson.com","feed_url":"https://www.aaron-gustafson.com/feeds/wai-aria.json","author":{"name":"Aaron Gustafson","url":"https://www.aaron-gustafson.com"},"icon":"https://www.aaron-gustafson.com/i/og-logo.png","favicon":"https://www.aaron-gustafson.com/favicon.png","expired":false,"items":[{"id":"https://www.aaron-gustafson.com/notebook/accessibility-assistant-for-figma-v52/","title":"✍🏻 Accessibility Assistant for Figma v52","summary":"I just hit “publish” on Accessibility Assistant for Figma v52 and I wanted to share some details on why this is a monumental release for us.","content_html":"<p>I just hit “publish” on <a href=\"https://www.figma.com/community/plugin/731310036968334777/accessibility-assistant\">Accessibility Assistant for Figma</a> v52 and I wanted to share some details on why this is a monumental release for us.</p>\n<p>We’re in the process of a major overhaul to this plugin. There was a lot of infrastructural work to do to modernize the plugin and set the stage for a host of new features to make designers more productive when it comes to making their designs more accessible. This release incorporates a lot of that foundational work, notably:</p>\n<ul>\n<li>Annotations are now presented as Figma-native Dev Mode annotations; this greatly reduces the working overhead of the plugin and reduces visual clutter in the document. We’ve also color-coordinated the icons in the Annotation Set viewer to the labels you see in the Dev Mode annotations, making it easier to scan.</li>\n<li>Legacy annotation tables will automatically be migrated into the new system. The visual readout tables will be hidden when this happens, but are still accessible if you need to copy or reference them. We’ve also included a tool to clean up these old layers when you’re ready.</li>\n<li>Annotations are now managed in a single UI rather than being separated, based on whether they impact focus order. This means you don’t need to jump back &amp; forth between tools to properly annotate your designs.</li>\n<li>We’ve organized and expanded the list of W3C roles available in the role picker. Additionally, the form now adapts to the role, offering you only the relevant fields and reducing distraction. We also added a description field, should you need it.</li>\n</ul>\n<p>We also fixed bugs related to duplicating layers. You can now copy layers and the annotations will go along for the ride, becoming a new Annotation Set. Similarly, you can now duplicate pages and the annotations — which are page-bound — will be re-generated. It’s worth noting that this may take some time on particularly large pages.</p>\n<p>This release has been a long time coming, but I’m incredibly proud of the team that’s been working so diligently on this, particularly Ashish Singh from HCL and Michael Fairchild, Scott O’Hara, and Ben Truelove from Microsoft. Their attention to detail and encyclopedic knowledge of accessibility has been instrumental in getting this project to the place that it is.</p>\n<p>And there’s more to come!</p>\n","social_text":"I just hit “publish” on Accessibility Assistant for Figma v52 and I wanted to share some details on why this is a monumental release for us.","url":"https://www.aaron-gustafson.com/notebook/accessibility-assistant-for-figma-v52/","tags":["accessibility","design","inclusive design","Microsoft","user experience","WAI-ARIA"],"date_published":"2026-02-20T23:27:28Z"},{"id":"https://www.aaron-gustafson.com/notebook/bring-focus-to-the-first-form-field-with-an-error/","title":"✍🏻 Bring Focus to the First Form Field with an Error","summary":"While filling out a long form the other day, I couldn’t figure out why it wasn’t submitting. Turns out I’d forgotten to fill in a field, but I didn’t know that because it had scrolled out of the viewport.","content_html":"<p>While filling out a long form the other day, I couldn’t figure out why it wasn’t submitting. Turns out I’d forgotten to fill in a field, but I didn’t know that because it had scrolled out of the viewport. This is a common problem on the web, but easily remedied with a little bit of JavaScript.</p>\n<h2 id=\"step-1%3A-make-the-most-of-your-markup\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-1%3A-make-the-most-of-your-markup\" aria-hidden=\"true\">#</a> Step 1: Make the Most of Your Markup</h2>\n<p>Whenever you’re building a form, you should use every tool in your toolbox for building that form properly. That means:</p>\n<ol>\n<li><a href=\"/notebook/labeled-with-love/\">Associate labels with their fields</a></li>\n<li>Use specialized <code>input</code> types (e.g., email, URL) as appropriate</li>\n<li>Identify required fields with <code>required</code> and <code>aria-required</code></li>\n<li>If you’re expecting a field to match a particular format, note that with <code>pattern</code> and provide an example with <code>placeholder</code></li>\n<li>Additional information about a field should be bound to it using <code>aria-describedby</code></li>\n</ol>\n<p>By following these steps, you’re likely already in a good place when it comes to your form’s UX and accessibility. Browsers will pay attention to the instructions in the markup, validate the user’s input, and even provide guidance on how to correct issues without you having to lift a finger. They’ll even focus the first invalid field on your behalf!</p>\n<p>But what if you want to customize the experience?</p>\n<h2 id=\"step-2%3A-enhanced-browser-validation\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-2%3A-enhanced-browser-validation\" aria-hidden=\"true\">#</a> Step 2: Enhanced Browser Validation</h2>\n<p>When you use proper markup for your forms, enhancing them with JavaScript becomes straightforward, thanks to the <a href=\"https://developer.mozilla.org/docs/Web/API/Constraint_validation\">Constraint Validation API</a>. Consider the following form field:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">required</span> <span class=\"token attr-name\">aria-required</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code></pre>\n<p>Using JavaScript, we can check to see it’s validity at any point:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\">document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>validity<span class=\"token punctuation\">.</span>valid<span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// Is either true or false</span></code></pre>\n<p>There are also a host of other properties on the field’s <code>validity</code> property that provide even more detail as to the state of the field’s validity (hence the name: <a href=\"https://developer.mozilla.org/docs/Web/API/ValidityState\"><code>ValidityState</code></a>). In the case of the field above, if <code>valueMissing</code> is <code>true</code> (relating back to that <code>required</code> attribute), <code>valid</code> is <code>false</code>.</p>\n<p>Armed with that knowledge, you could use another feature of the <a href=\"https://developer.mozilla.org/docs/Web/API/Constraint_validation\">Constraint Validation API</a> to show a custom error message in the browser UI:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">var</span> input <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>input<span class=\"token punctuation\">.</span>validity<span class=\"token punctuation\">.</span>valid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  input<span class=\"token punctuation\">.</span><span class=\"token function\">setCustomValidity</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Please enter your name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  input<span class=\"token punctuation\">.</span><span class=\"token function\">reportValidity</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The thing is, you don’t really want to litter your JavaScript with strings like that. It’s not maintainable. Thankfully, we can leverage markup to achieve the same goal:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span>\n  <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">required</span>\n  <span class=\"token attr-name\">aria-required</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-error-required</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Please enter your name<span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">/></span></span></code></pre>\n<p>The <code>input</code> in this example has a <a href=\"https://developer.mozilla.org/docs/Learn/HTML/Howto/Use_data_attributes\">data attribute</a> containing the error string (<code>data-error-required</code>). We can create whatever data attributes we want and access them using that element’s <code>dataset</code> property. It’s worth noting that hyphenated property names become camelCase when accessed as a named property of <code>dataset</code>.</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">var</span> input <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>input<span class=\"token punctuation\">.</span>validity<span class=\"token punctuation\">.</span>valid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  input<span class=\"token punctuation\">.</span><span class=\"token function\">setCustomValidity</span><span class=\"token punctuation\">(</span>input<span class=\"token punctuation\">.</span>dataset<span class=\"token punctuation\">.</span>errorRequired<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  input<span class=\"token punctuation\">.</span><span class=\"token function\">reportValidity</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>With that, we get the same result with far looser coupling between individual fields and the JavaScript handling validation.</p>\n<figure id=\"fig-2022-08-22-01\" class=\"media-container\">\n<p><img src=\"https://www.aaron-gustafson.com/i/posts/2022-08-22/01.jpg\" alt=\"This custom validation string as rendered in the error tooltip in Safari 15.6\"></p>\n</figure>\n<p>You can even extend the approach to handle different kinds of errors:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span>\n  <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>email<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>email<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>email<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">required</span>\n  <span class=\"token attr-name\">aria-required</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-error-required</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Please enter your email<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-error-invalid</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Your email doesn’t look right<span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">/></span></span></code></pre>\n<p>Here I’m using two different data attributes to apply in different error scenarios and the one I show will depend on the type of error a user has encountered. Pretty cool!</p>\n<p>And since we’re still operating in the context of the browser’s built-in validation experience, users will still get directed to the first field with an error when they submit the form.</p>\n<p>But what if you want to bypass the built-in experience and go full custom?</p>\n<h2 id=\"step-3%3A-going-rogue\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#step-3%3A-going-rogue\" aria-hidden=\"true\">#</a> Step 3: Going Rogue</h2>\n<p>The built-in browser validation UI is pretty great, but maybe it’s not your cup of tea. Thankfully, it’s pretty easy to take the training wheels off. You just add a <code>novalidate</code> attribute to the <code>form</code> element. But before you go dropping that attribute in your markup, consider that your custom validation code will all be JavaScript and if that fails to run—<a href=\"/notebook/progressive-misconceptions/\">yes, it happens</a>—the browser won’t step in and fill the void. So instead of putting it in your markup, inject it into the <code>form</code> when you know absolutely all of the JavaScript code necessary to run your custom validation experience is loaded and ready to rock. In fact, it should be the last line of code to execute:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token comment\">// Validation Logic Definition</span>\n<span class=\"token comment\">// including validateMe() function</span>\n\ndocument<span class=\"token punctuation\">.</span><span class=\"token function\">querySelectorAll</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"form\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">$form</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  $form<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"submit\"</span><span class=\"token punctuation\">,</span> validateMe<span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  $form<span class=\"token punctuation\">.</span><span class=\"token function\">setAttribute</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"novalidate\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>With that in place, we can turn our attention to handling the validation setup.</p>\n<p>For simplicity, and based on personal preference, I am going to start with setting up my form to validate when the form is submitted rather than whenever an individual field is changed (hence the “submit” event listener). When the event is fired, the event handler will loop through the fields in the form and validate each one. For the sake of the widest possible browser compatibility, I’m foregoing fat arrow functions and other ES2015 goodies and rockin’ this old school.</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">function</span> <span class=\"token function\">validateMe</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">var</span> $form <span class=\"token operator\">=</span> e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">,</span>\n    i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n    field_count <span class=\"token operator\">=</span> $form<span class=\"token punctuation\">.</span>elements<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">,</span>\n    $first_error <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> field_count<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">var</span> $field <span class=\"token operator\">=</span> $form<span class=\"token punctuation\">.</span>elements<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n      valid <span class=\"token operator\">=</span> <span class=\"token function\">isValid</span><span class=\"token punctuation\">(</span>$field<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>$first_error <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">!</span>valid<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      $first_error <span class=\"token operator\">=</span> $field<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>$first_error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    e<span class=\"token punctuation\">.</span><span class=\"token function\">preventDefault</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    $first_error<span class=\"token punctuation\">.</span><span class=\"token function\">focus</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>First, I get a reference to the form that needs to be validated, then I set up the loop for each of the fields. I also set up a reference to the first field with an error—that is the point of the article after all—as <var>$first_error</var> and set it to <code>false</code>.</p>\n<p>Within the loop, I grab a reference to the field and pipe it into another function that will do the actual validation (<code>isValid()</code>). That function will return <code>true</code> if the field is valid and <code>false</code> if it isn’t. The last bit of the loop checks to see if <var>$first_error</var> has been set already and, if it hasn’t, sets it to the current field if it isn’t valid.</p>\n<p>Finally, I check to see if <var>$first_error</var> is set (i.e., true) and if it is, the form has an issue, so I prevent the default behavior of the submit event (using <code>preventDefault()</code>) and focus the field captured in <var>$first_error</var>.</p>\n<h2 id=\"addendum%3A-associating-custom-error-messages\" tabindex=\"-1\"><a class=\"header-anchor\" href=\"#addendum%3A-associating-custom-error-messages\" aria-hidden=\"true\">#</a> Addendum: Associating Custom Error Messages</h2>\n<p>I don’t want to get too into the weeds with my <code>isValid()</code> method, as you can see the end result at the bottom of this post, but I do want to take a moment to describe how you should be handling inline field errors.</p>\n<p>First off, you will need to add <code>aria-invalid=&quot;true&quot;</code> to any fields that have an error. Secondly, you will want to inject the error message into the markup, give its container an <code>id</code>, and <a href=\"https://developer.mozilla.org/docs/Web/Accessibility/ARIA/Attributes/aria-errormessage\">associate it with the field using <code>aria-errormessage</code></a>. So when your JavaScript is done with it, your field will look something like this:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>label</span> <span class=\"token attr-name\">for</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>What’s Your Name?<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>label</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span>\n  <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">required</span>\n  <span class=\"token attr-name\">aria-required</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">data-error-required</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Please enter your name<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">aria-errormessage</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name-validation-error<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">aria-invalid</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>strong</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>form-validation-error<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">id</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>name-validation-error<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token punctuation\">></span></span>Please enter your name<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>strong</span>\n<span class=\"token punctuation\">></span></span></code></pre>\n<p>It’s also worth noting that you’ll want to reset and re-validate the form field once the user has changed the contents of the field (and hopefully remediated the error). Resetting the field will involve removing the <code>aria-invalid</code> attribute and doing one of two things with the error message: either remove it from the markup entirely or simply hide it (e.g., <code>display: none</code>). Once the <code>aria-invalid</code> state is reset, it doesn’t matter that there is an existing <code>aria-errormessage</code> attribute. That said, I generally prefer to totally reset the field entirely, removing both attributes and the validation error element as well.</p>\n<p>Here you can see <a href=\"https://codepen.io/aarongustafson/pen/eYMXMPP\">a complete working prototype of this approach</a>:</p>\n<iframe class=\"codepen\" height=\"400\" style=\"width:100%;\" scrolling=\"no\" title=\"CodePen Embed\" src=\"https://codepen.io/anon/embed/eYMXMPP?height=400&theme-id=dark&default-tab=result\" frameborder=\"0\" loading=\"lazy\" allowtransparency=\"true\" allowfullscreen=\"true\"><p><a href=\"https://codepen.io/aarongustafson/pen/eYMXMPP\" target=\"_blank\" rel=\"noopener\">See the Pen</a></p></iframe>\nHopefully this helps you with the development of your own forms. Good luck!\n","social_text":"When highlighting form errors, moving focus to the first error encountered will ensure the error is seen and remedied.","url":"https://www.aaron-gustafson.com/notebook/bring-focus-to-the-first-form-field-with-an-error/","tags":["accessibility","forms","HTML","inclusive design","JavaScript","progressive enhancement","WAI-ARIA","web design"],"image":"https://www.aaron-gustafson.com/i/posts/2022-08-22/hero.jpg","date_published":"2022-08-22T21:16:02Z"},{"id":"https://www.aaron-gustafson.com/notebook/aria-quicktip-labelledby-vs-describedby/","title":"✍🏻 ARIA Quicktip: Labelledby vs. Describedby","summary":"The difference between the <code>aria-labelledby</code> and <code>aria-describedby</code> attributes is not obvious. Here’s a bit of a clarification for using them in forms.","content_html":"<p>Last night, while we were enjoying a cool evening and a few drinks outside after day 1 of <a href=\"https://bdconf.com\">BDConf</a>, <a href=\"https://adactio.com\">Jeremy</a> asked me for some clarification on the ARIA attributes I had demoed as part of <a href=\"https://www.slideshare.net/AaronGustafson/falling-in-love-with-forms-bdconf-2014\">my forms presentation</a> earlier in the afternoon. In particular, he was confused by how <code>aria-labelledby</code> and <code>aria-describedby</code> differ.</p>\n<p>I hadn’t really thought about it before, but it’s a good question. They seem pretty similar in function, right? And both support a space separated list of one or more <code>id</code> references. It’s downright confusing.</p>\n<p>My simple explanation was that, at least in terms of form fields, they differ in when they are read. The <code>aria-labelledby</code> attribute replaces the associated <code>label</code> element (which is, of course, associated with the field via the <code>label</code>’s <code>for</code> attribute). The <code>aria-describedby</code> attribute, on the other hand, is read after the field type is stated.</p>\n<p>To demonstrate how all of this plays out, I threw together <a href=\"https://codepen.io/aarongustafson/pen/dmuoe/\">a quick CodePen demo</a> that takes you through numerous ways you can use and combine these attributes. I also did a <a href=\"https://youtu.be/U8_VjI-Z1LA\">screen recording to demonstrate how ChromeVox exposes these attributes</a>:</p>\n<p><a href=\"https://www.youtube.com/watch?v=U8_VjI-Z1LA\">https://www.youtube.com/watch?v=U8_VjI-Z1LA</a></p>\n<p><strong>Update:</strong> <a href=\"https://twitter.com/stevefaulkner\">Steve Faulkner</a> shared a doc that discusses <a href=\"https://www.w3.org/TR/accname-1.1/#x4-3-accessible-name-and-description-computation\">how accessible names and descriptions are calculated</a>. Thanks Steve!</p>\n<p><em>Note: I did discover a bug in ChromeVox wherein the content of the elements referenced in <code>aria-describedby</code> are not read when the field receives focus via the keyboard (using the <kbd>tab</kbd> key), but it does when it receives focus via the mouse. I’ve submitted <a href=\"https://code.google.com/p/google-axs-chrome/issues/detail?id=158&amp;thanks=158&amp;ts=1415202123\">a bug report</a> to to the powers that be.</em></p>\n","url":"https://www.aaron-gustafson.com/notebook/aria-quicktip-labelledby-vs-describedby/","tags":["accessibility","web design","WAI-ARIA"],"date_published":"2014-11-05T15:45:22Z"},{"id":"https://www.aaron-gustafson.com/publications/articles/improving-the-tweet-box/","title":"📄 Improving the Tweet Box","content_html":"<p><a href=\"http://Twitter.com\">Twitter.com</a>’s redesign was much welcomed and rightly so. I explored its most prominent feature: the tweet box, and looks at how it can be made more accessible with just a few minor adjustments.</p>\n","url":"http://webstandardssherpa.com/reviews/improving-the-tweet-box","tags":["web development","JavaScript","WAI-ARIA","HTML"],"date_published":"2011-03-03T00:00:00Z"},{"id":"https://www.aaron-gustafson.com/publications/articles/create-a-tabbed-interface-part-2/","title":"📄 Create a Tabbed Interface, Part 2","content_html":"<p>Building on the first article, in this piece I focus on making the JavaScript more flexible and accessible.</p>\n","url":"https://www.slideshare.net/AaronGustafson/create-a-tabbed-interface-part-2","tags":["progressive enhancement","JavaScript","HTML","WAI-ARIA"],"date_published":"2009-11-01T00:00:00Z"},{"id":"https://www.aaron-gustafson.com/publications/articles/create-a-tabbed-interface-part-1/","title":"📄 Create a Tabbed Interface, Part 1","content_html":"<p>In the first of a two-part tutorial, I demonstrate how to create a script for a lightweight yet powerful tabbed interface using CSS and basic JavaScript.</p>\n","url":"https://www.slideshare.net/AaronGustafson/create-a-tabbed-interface-part-1","tags":["progressive enhancement","JavaScript","HTML","WAI-ARIA"],"date_published":"2009-10-01T00:00:00Z"}]}