<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>HTMHell Advent Calendar 2025</title>
  <subtitle>The HTMHell 2025 advent calendar.</subtitle>
  <link href="https://htmhell.dev/feed_advent.xml" rel="self"/>
  <link href="https://htmhell.dev/adventcalendar"/>
  <updated>2024-11-26T00:00:00Z</updated>
  <id>https://htmhell.dev/adventcalendar</id>
  <author>
    <name>Manuel Matuzovic</name>
    <email>manuel@matuzo.at</email>
  </author>
  
  
    
  
  <entry>
    <title>HTML Input Validation is (maybe) Good</title>
    <link href="https://htmhell.dev/adventcalendar/2025/28/"/>
    <updated>2025-12-28T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/28/</id>
    <content type="html">by Wes Goulet&lt;br&gt;&lt;p&gt;I think of client-side validation as a progressive enhancement for your users. You have to validate user input on the server (you can&#39;t trust what comes from the client), but some validation on the client makes for a nice UX. But that doesn&#39;t have to mean lots of JS code or using some validation library on your client. You can get pretty far with the browser&#39;s built-in HTML input validation. And then you can layer a little bit of JS on top of that to make it even better.&lt;/p&gt;
&lt;p&gt;Let&#39;s take a look at a text input. You can use &lt;code&gt;pattern&lt;/code&gt;, &lt;code&gt;minlength&lt;/code&gt; and &lt;code&gt;maxlength&lt;/code&gt; to provide constraints. You can use &lt;code&gt;title&lt;/code&gt; to provide error message. You can conditionally style invalid input with &lt;code&gt;:user-invalid&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;program_name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Name of program&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;program_name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;minlength&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;maxlength&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;20&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;[a-zA-Z0-9]+&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Only alphabetical and numerical characters are accepted&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;required&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;input:user-invalid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 4px solid red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the user attempts to submit the form the browser takes care of validating and showing the message.&lt;/p&gt;
&lt;figure style=&quot;margin: 4rem 0;&quot;&gt;
    &lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/28/chromium.jpg&quot; alt=&quot;A screenshot of Chrome.  The error message says &#39;Please match the requested format. Only alphabetical and numerical characters are accepted&#39;&quot; style=&quot;border: 1px solid #ccc;&quot; /&gt;
    &lt;figcaption&gt;Example validation message on Chrome&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;margin: 4rem 0;&quot;&gt;
    &lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/28/firefox.jpg&quot; alt=&quot;A screenshot of Firefox.  The error message says &#39;Please match the requested format: Only alphabetical and numerical characters are accepted.&#39;&quot; style=&quot;border: 1px solid #ccc;&quot; /&gt;
    &lt;figcaption&gt;Example validation message on Firefox&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;margin: 4rem 0;&quot;&gt;
    &lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/28/safari.jpg&quot; alt=&quot;A screenshot of Safari.  The error message says &#39;Match the requested format: Only alphabetical and numerical characters are accepted&#39;&quot; style=&quot;border: 1px solid #ccc;&quot; /&gt;
    &lt;figcaption&gt;Example validation message on Safari&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure style=&quot;margin: 4rem 0;&quot;&gt;
    &lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/28/ios.jpeg&quot; alt=&quot;A screenshot of Safari on iOS.  The error message says &#39;Match the requested format: Only alphabetical and numerical characters are accepted&#39;&quot; style=&quot;border: 1px solid #ccc;&quot; /&gt;
    &lt;figcaption&gt;Example validation message on Safari on iOS&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;You can play with a live example at &lt;a href=&quot;https://codepen.io/wes_goulet/pen/emJjqKj&quot;&gt;this CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;BTW, I just noticed that Chrome and Firefox say &amp;quot;Please&amp;quot; but Safari doesn&#39;t 😃&lt;/p&gt;
&lt;h2 id=&quot;styling&quot;&gt;Styling&lt;/h2&gt;
&lt;p&gt;You can&#39;t style the error popup, so if that&#39;s important to you then maybe you need to write your own error UI. A lot of times I don&#39;t mind leaning on browser UI when it&#39;s available (ie: most of the time I don&#39;t need my error messages in my website&#39;s overall brand/styling). Also, I think a lot of users have seen the browser&#39;s error UI before (from other sites that use native form validation), so there is some familiarity there for the user.&lt;/p&gt;
&lt;h2 id=&quot;the-problem-accessibility&quot;&gt;The Problem: Accessibility&lt;/h2&gt;
&lt;p&gt;Unfortunately, native form validation isn&#39;t very accessible.&lt;/p&gt;
&lt;p&gt;I had assumed it was accessible, because most of the time when I lean on the browser to do something it handles accessibility much better than any userland code I would write. But after reading &lt;a href=&quot;https://adrianroselli.com/2019/02/avoid-default-field-validation.html&quot;&gt;this excellent post from Adrian Roselli&lt;/a&gt; (an accessibility expert), I learned my assumption was wrong.&lt;/p&gt;
&lt;p&gt;The main accessibility issues with native form validation are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Error messages aren&#39;t associated with form fields&lt;/strong&gt; - Screen readers don&#39;t reliably announce which field has an error, so users relying on assistive technology can&#39;t easily figure out what needs to be fixed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error messages disappear too quickly&lt;/strong&gt; - The browser&#39;s error bubble might disappear before users can read it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Error messages don&#39;t respect user text size/spacing preferences&lt;/strong&gt; - The error bubble text doesn&#39;t resize with browser zoom settings or respect text spacing preferences.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Related to all this, &lt;a href=&quot;https://github.com/w3c/wcag/pull/4431&quot;&gt;a recent update to WCAG&lt;/a&gt; acknowledges these accessibility issues with native form validation.&lt;/p&gt;
&lt;h2 id=&quot;make-it-better-with-js&quot;&gt;Make it better with JS&lt;/h2&gt;
&lt;p&gt;I originally wrote this post to point out that native form validation is good enough (lean on the browser!) and that&#39;s all you need. But after reading about the accessibility issues, I think the right answer is using native form validation as the foundation, and then adding a bit of JS to make it more accessible.&lt;/p&gt;
&lt;p&gt;We&#39;ll use the Constraint Validation API, which is the JavaScript interface for HTML form validation. It allows you to programmatically check if a form field is valid, get validation messages, and customize how errors are displayed to users. For example, you can check if an input is valid:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; element &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;program_name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;checkValidity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// returns true or false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also get the validation message:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; element &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;program_name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;validationMessage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// returns the error message if invalid&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;ll use the Constraint Validation API and follow &lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Understanding/error-identification.html&quot;&gt;WCAG input error guidance&lt;/a&gt; to create our own error messages that are properly associated with form fields. Here&#39;s a simple example:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;program_name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Name of program&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;program_name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;minlength&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;maxlength&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;20&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;[a-zA-Z0-9]+&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Only alphabetical and numerical characters are accepted&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;required&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;aria-describedby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;program_name-error&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;program_name-error&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alert&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;my-form&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; input &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;program_name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; errorMessage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;program_name-error&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// IMPORTANT: set this attribute in JS, that way it&#39;s a&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// progressive enhancement (ie: if JS isn&#39;t available the&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// native form validation will still work).&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;novalidate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateInput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isValid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;checkValidity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  errorMessage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; isValid &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;validationMessage&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isValid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;aria-invalid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;aria-invalid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Validate on blur (when user leaves the field)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;blur&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; validateInput&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Clear errors as user types&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;input&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;checkValidity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    errorMessage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;aria-invalid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Handle form submit&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;checkValidity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;// Update validation state for all fields&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;validateInput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The form has &lt;code&gt;novalidate&lt;/code&gt; to turn off the browser&#39;s built-in validation (added via JavaScript so it degrades gracefully).&lt;/li&gt;
&lt;li&gt;The error message is associated with the input using &lt;code&gt;aria-describedby&lt;/code&gt;, so screen readers will announce it when the field is focused.&lt;/li&gt;
&lt;li&gt;The error message has &lt;code&gt;role=&amp;quot;alert&amp;quot;&lt;/code&gt; so screen readers will announce it when it appears.&lt;/li&gt;
&lt;li&gt;The input gets &lt;code&gt;aria-invalid&lt;/code&gt; set appropriately, clearly marking it for assistive technologies.&lt;/li&gt;
&lt;li&gt;Validation happens on &lt;code&gt;blur&lt;/code&gt; (when the user leaves the field) and on form submit.&lt;/li&gt;
&lt;li&gt;The error message stays visible, giving users time to read it.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;You can play with a live example at &lt;a href=&quot;https://codepen.io/wes_goulet/pen/emJjqKj&quot;&gt;this CodePen&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This &lt;a href=&quot;https://cloudfour.com/thinks/progressively-enhanced-form-validation-part-2-layering-in-javascript/&quot;&gt;post by Cloud Four&lt;/a&gt; spells out a more complete solution in detail. (If you mainly support evergreen browsers then I wouldn&#39;t worry too much about the first part &amp;quot;Removing invalid styles on page load for all browsers&amp;quot; since Chrome has shipped support for &lt;code&gt;:user-invalid&lt;/code&gt; for &lt;a href=&quot;https://caniuse.com/wf-user-pseudos&quot;&gt;a couple years now&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;So native HTML form validation is a good starting point, but it&#39;s not enough on its own due to accessibility issues. You can use the Constraint Validation API to layer on accessible error messages with a bit of JavaScript. That way you get the browser&#39;s validation working as a baseline, and then enhance it to be accessible when JS is available.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://matuzo.at/&quot;&gt;Manuel&lt;/a&gt; for reviewing this post and pointing out the accessibility issues with native form validation.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Replacing JS with just HTML</title>
    <link href="https://htmhell.dev/adventcalendar/2025/27/"/>
    <updated>2025-12-27T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/27/</id>
    <content type="html">by Aaron T. Grogg&lt;br&gt;&lt;p&gt;For many years now, JavaScript has been the workhorse of the web. If you wanted to do something that couldn&#39;t be done with just HTML and CSS, you could usually find a way to do it with JS.&lt;br /&gt;
And that is great! JS has helped push user experiences forward, and honestly helped push HTML and CSS forward!&lt;/p&gt;
&lt;p&gt;But as time marches on, and the HTML and CSS methods &lt;a href=&quot;https://webstatus.dev/?q=%28group%3Ahtml+OR+css%29&amp;amp;sort=name_asc&quot;&gt;gain traction&lt;/a&gt;, we need to start replacing the old JS methods that feel so comfy with new methods that require less JS.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Nothing against JS&lt;/strong&gt;&lt;/em&gt;, but it has better things to do than setup and manage your accordions or offscreen navigation menus... Plus, JS needs to be downloaded, decompressed, evaluated, processed, and then often consumes memory to monitor and maintain features. If we can &lt;em&gt;hand-off&lt;/em&gt; any JS functionality to native HTML or CSS, then users can download less stuff, and the remaining JS can pay attention to more important tasks that HTML and CSS can&#39;t handle (yet).&lt;/p&gt;
&lt;p&gt;Below are a few examples; any you care to add?&lt;/p&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of Contents:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://htmhell.dev/adventcalendar/2025/27/#accordions-expanding-content-panels&quot;&gt;Accordions / Expanding Content Panels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://htmhell.dev/adventcalendar/2025/27/#input-with-autofilter-suggestions-dropdown&quot;&gt;Input with Autofilter Suggestions Dropdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://htmhell.dev/adventcalendar/2025/27/#modals-popovers&quot;&gt;Modals / Popovers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://htmhell.dev/adventcalendar/2025/27/#offscreen-nav-content&quot;&gt;Offscreen Nav / Content&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;accordions-/-expanding-content-panels&quot;&gt;Accordions / Expanding Content Panels&lt;/h2&gt;
&lt;h3 id=&quot;description&quot;&gt;Description:&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;details&lt;/code&gt; and &lt;code&gt;summary&lt;/code&gt; HTML elements provide an HTML-only replacement to the typical JS accordion:&lt;br /&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/27/accordion-expanding-content.gif&quot; alt=&quot;Examples of HTML  element expanding and contracting&quot; /&gt;&lt;br /&gt;
CopePen: &lt;a href=&quot;https://codepen.io/aarontgrogg/pen/GgoOqVX&quot;&gt;Accordion / Expanding Content&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;use-cases&quot;&gt;Use cases:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hiding/showing content&lt;/li&gt;
&lt;li&gt;Expanding content sections&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;basic-implementation&quot;&gt;Basic implementation:&lt;/h3&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Initially closed, click to open&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Content is initially hidden, but can be revealed by clicking the summary.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add an &lt;code&gt;open&lt;/code&gt; attribute to set the default appearance as &amp;quot;open&amp;quot;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Initially open, click to close&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Content is initially visible, but can be hidden by clicking the summary.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use the same &lt;code&gt;name&lt;/code&gt; attribute on all related &lt;code&gt;details&lt;/code&gt; (like radio buttons) to restrict only one open panel at a time:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;foo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Initially open, clicking others will close this&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Content is initially visible, but can be hidden by clicking the summary; only one panel can be open at a time.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;foo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Initially closed, clicking will open this, and close others&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Content is initially hidden, but can be revealed by clicking the summary; only one panel can be open at a time.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;foo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Initially closed, clicking will open this, and close others&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Content is initially hidden, but can be revealed by clicking the summary; only one panel can be open at a time.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also customize the appearance with CSS and trigger the open/close via JS.&lt;/p&gt;
&lt;p&gt;Learn more about the &lt;code&gt;details&lt;/code&gt; element in the previously-published “&lt;a href=&quot;https://www.htmhell.dev/adventcalendar/2025/23&quot;&gt;For the Love of &amp;lt;details&amp;gt;&lt;/a&gt;&amp;quot;.&lt;/p&gt;
&lt;h3 id=&quot;resources&quot;&gt;Resources:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details&quot;&gt;MDN &lt;code&gt;details&lt;/code&gt; page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.codewithshripal.com/playground/html/details-element&quot;&gt;&amp;lt;details&amp;gt; element&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;browser-compatibility&quot;&gt;Browser compatibility:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details#browser_compatibility&quot;&gt;MDN &lt;code&gt;details&lt;/code&gt; Browser Compatibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;input-with-autofilter-suggestions-dropdown&quot;&gt;Input with Autofilter Suggestions Dropdown&lt;/h2&gt;
&lt;h3 id=&quot;description-2&quot;&gt;Description:&lt;/h3&gt;
&lt;p&gt;Combining the HTML &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;datalist&lt;/code&gt; elements can create a dropdown of options that autofilters as you type:&lt;br /&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/27/input-with-datalist.gif&quot; alt=&quot;Examples of HTML  and  providing autofilter dropdown&quot; /&gt;&lt;br /&gt;
CodePen: &lt;a href=&quot;https://codepen.io/aarontgrogg/pen/yyePPor&quot;&gt;Input with Autofilter Suggestions Dropdown&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;use-cases-2&quot;&gt;Use cases:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Site search&lt;/li&gt;
&lt;li&gt;Product search or filter&lt;/li&gt;
&lt;li&gt;Filter any list of data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;basic-implementation-2&quot;&gt;Basic implementation:&lt;/h3&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browser&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Browser&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;       &lt;span class=&quot;token attr-name&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browsers&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;       &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browser&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browser&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;       &lt;span class=&quot;token attr-name&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;50&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token attr-name&quot;&gt;autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;off&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;datalist&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browsers&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Arc&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Brave&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Chrome&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;DuckDuckGo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Firefox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Microsoft Edge&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Opera&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Safari&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Tor&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Vivaldi&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;datalist&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also use other input types:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Quantity&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;       &lt;span class=&quot;token attr-name&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quantity-options&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quantity&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;datalist&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;quantity-options&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;5&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;10&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;20&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;50&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;datalist&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;appointment&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Appointment&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;time&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;       &lt;span class=&quot;token attr-name&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;appointments&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;appointment&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;appointment&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;datalist&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;appointments&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;12:00&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;13:00&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;14:00&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;datalist&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that, at the time of this writing, Firefox was limited to only textual-based input types, so no &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;time&lt;/code&gt;, &lt;code&gt;range&lt;/code&gt; or &lt;code&gt;color&lt;/code&gt; for now... :-(&lt;/p&gt;
&lt;p&gt;Also note that, at the time of this writing, &lt;a href=&quot;https://htmhell.dev/adventcalendar/2025/5/#the-list-attribute-on-lessinputgreater-elements&quot;&gt;there are limitations on mobile, and accessibility concerns&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;resources-2&quot;&gt;Resources:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist&quot;&gt;MDN &lt;code&gt;datalist&lt;/code&gt; page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sitepoint.com/html5-datalist-autocomplete/&quot;&gt;HTML5 datalist autocomplete&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;browser-compatibility-2&quot;&gt;Browser compatibility:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist#browser_compatibility&quot;&gt;MDN &lt;code&gt;datalist&lt;/code&gt; Browser Compatibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;modals-/-popovers&quot;&gt;Modals / Popovers&lt;/h2&gt;
&lt;h3 id=&quot;description-3&quot;&gt;Description:&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;popover&lt;/code&gt; and &lt;code&gt;popovertarget&lt;/code&gt; attributes can replace the traditional JS-driven modal/popover/overlay:&lt;br /&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/27/modal-popover.gif&quot; alt=&quot;Examples of HTML  elements opening and closing&quot; /&gt;&lt;br /&gt;
CodePen: &lt;a href=&quot;https://codepen.io/aarontgrogg/pen/QwyOKNW&quot;&gt;Modal / Popover&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;use-cases-3&quot;&gt;Use cases:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hiding/showing side panels / additional information&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;basic-implementation-3&quot;&gt;Basic implementation&lt;/h3&gt;
&lt;p&gt;An &lt;code&gt;auto&lt;/code&gt; popover (default) can be &amp;quot;light dismissed&amp;quot; (clicking outside of it or hitting the &lt;code&gt;esc&lt;/code&gt; key). Opening an &lt;code&gt;auto&lt;/code&gt; automatically closes any other &lt;code&gt;auto&lt;/code&gt; popovers that were open. Clicking the &lt;code&gt;button&lt;/code&gt; a second time will close the one it opened.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popovertarget&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pop-auto&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   Toggle Popover&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dialog&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popover&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pop-auto&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   I&#39;m an &quot;auto&quot; Popover!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;hint&lt;/code&gt; popover can also be &amp;quot;light dismissed&amp;quot;. It does &lt;em&gt;not&lt;/em&gt; close other &lt;code&gt;hint&lt;/code&gt; popovers when opened. Clicking the &lt;code&gt;button&lt;/code&gt; a second time will close the one it opened.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popovertarget&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pop-hint&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   Toggle Popover&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dialog&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popover&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;hint&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pop-hint&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   I&#39;m a &quot;hint&quot; Popover!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that, at the time of this writing, Firefox and all iOS varieties do not support &lt;code&gt;hint&lt;/code&gt; popovers.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;manual&lt;/code&gt; popover can &lt;em&gt;not&lt;/em&gt; be &amp;quot;light dismissed&amp;quot;. It does &lt;em&gt;not&lt;/em&gt; close other &lt;code&gt;manual&lt;/code&gt; popovers when opened. Clicking the &lt;code&gt;button&lt;/code&gt; a second time will close the one it opened.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popovertarget&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pop-manual&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   Toggle Popover&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dialog&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popover&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;manual&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pop-manual&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   I&#39;m a &quot;manual&quot; Popover!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Learn more about the opening and closing dialogs and popovers in the previously-published “&lt;a href=&quot;https://www.htmhell.dev/adventcalendar/2025/7&quot;&gt;Controlling dialogs and popovers with the Invoker Commands API&lt;/a&gt;&amp;quot;.&lt;/p&gt;
&lt;h3 id=&quot;resources-3&quot;&gt;Resources:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/popover&quot;&gt;MDN &lt;code&gt;popover&lt;/code&gt; page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mdn.github.io/dom-examples/popover-api/&quot;&gt;Popover API examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/blog/introducing-popover-api/&quot;&gt;Introducing the popover API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/jh3y/pen/XWPBmmo&quot;&gt;Popover API!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=KX8YQW7stzs&quot;&gt;HTMHell #5 - An introduction to the popover attribute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=RVxl5nZY790&quot;&gt;The accessibility of the popover attribute&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;browser-compatibility-3&quot;&gt;Browser compatibility:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/popover#browser_compatibility&quot;&gt;MDN &lt;code&gt;popover&lt;/code&gt; Browser Compatibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;offscreen-nav-/-content&quot;&gt;Offscreen Nav / Content&lt;/h2&gt;
&lt;h3 id=&quot;description-4&quot;&gt;Description:&lt;/h3&gt;
&lt;p&gt;The above Modal / Popover functionality can also be used to create an offscreen navigation that requires no JS:&lt;br /&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/27/offscreen-nav.gif&quot; alt=&quot;Example of HTML Popover used as an offscreen navigation menu&quot; /&gt;&lt;/p&gt;
&lt;p&gt;CodePen: &lt;a href=&quot;https://codepen.io/aarontgrogg/pen/wBMPMVG&quot;&gt;Offscreen Content&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;use-cases-4&quot;&gt;Use cases:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hiding/showing navigation menus&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;basic-implementation-4&quot;&gt;Basic implementation:&lt;/h3&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popovertarget&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;menu&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   Toggle Menu&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;nav&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popover&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;menu&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   Nav Content&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;nav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#menu&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 100vh&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -100vw&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#menu:popover-open&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;translate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I use a &lt;code&gt;nav&lt;/code&gt; element to give it semantic value, but you can use any HTML element (&lt;code&gt;div&lt;/code&gt;, &lt;code&gt;section&lt;/code&gt;, &lt;code&gt;aside&lt;/code&gt;, etc.).&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;popover&lt;/code&gt; defaults to &lt;code&gt;position: fixed&lt;/code&gt; per the User Agent Stylesheet, and is simply pushed off screen when closed, and pulled back onscreen when it is open. Note that &lt;code&gt;margin: 0&lt;/code&gt; is required if you want to override the User Agent center-alignment.&lt;/p&gt;
&lt;p&gt;Clicking outside of the above menu closes it. You can force the panel to stay open, requiring a manual/explicit close, by using &lt;code&gt;popover=&amp;quot;manual&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can also add a &lt;code&gt;backdrop&lt;/code&gt; pseudo element and style it as you wish:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#menu::backdrop&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;rgb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;190 190 190 / 75%&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;resources-4&quot;&gt;Resources:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/popover&quot;&gt;MDN &lt;code&gt;popover&lt;/code&gt; page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mdn.github.io/dom-examples/popover-api/&quot;&gt;MDN Popover API examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/blog/introducing-popover-api/&quot;&gt;Introducing the popover API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codepen.io/jh3y/pen/XWPBmmo&quot;&gt;Popover API!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;browser-compatibility-4&quot;&gt;Browser compatibility:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/popover#browser_compatibility&quot;&gt;MDN &lt;code&gt;popover&lt;/code&gt; Browser Compatibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;While we all love the power and flexibility JS provides, we should also respect it, and our users, by limiting its use to what it &lt;em&gt;needs&lt;/em&gt; to do.&lt;/p&gt;
&lt;p&gt;There is &lt;strong&gt;so&lt;/strong&gt; much more that has changed in recent years, including a ton of options that CSS now covers. If you are now hungry for more, have a look at [my longer article that covers those as well](&lt;a href=&quot;https://aarontgrogg.com/blog/2023/05/31/replace-js-with-no-js-or-lo-js-options/&quot;&gt;https://aarontgrogg.com/blog/2023/05/31/replace-js-with-no-js-or-lo-js-options/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy reducing!&lt;br /&gt;
Atg&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Class names for content not design</title>
    <link href="https://htmhell.dev/adventcalendar/2025/26/"/>
    <updated>2025-12-26T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/26/</id>
    <content type="html">by Darice de Cuba&lt;br&gt;&lt;p&gt;One of the first thing I learned when I started coding HTML, besides using &lt;code&gt;div&lt;/code&gt; instead of &lt;code&gt;tables&lt;/code&gt; for the layout, was naming classes. One of the core ideas being that with HTML and CSS we keep content separate from design. A website should have solid HTML and class names in such a way that you can redesign the website by only editing the CSS and maybe a little bit of the HTML.&lt;/p&gt;
&lt;p&gt;But to do that, the class and id names need to be reusable. If you make the class names design and layout specific, you will have to edit your HTML files every time you want to change these elements their position or design, instead of only editing the CSS file.&lt;/p&gt;
&lt;p&gt;Due to the use of frameworks, a lot of sites nowadays have become a div and class soup that makes the HTML code unreadable and hard to troubleshoot. Developers who never learnt to code HTML from scratch lack the basic understanding of a solid HTML layout with good class names.&lt;/p&gt;
&lt;h2 id=&quot;generic-class-names&quot;&gt;Generic class names&lt;/h2&gt;
&lt;p&gt;Some example of bad class names are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;h1 class=&amp;quot;text-header-blue&amp;quot;&amp;gt;&lt;/code&gt; a better way is &lt;code&gt;&amp;lt;h1 class=&amp;quot;site-name&amp;quot;&amp;gt;&lt;/code&gt; and for articles &lt;code&gt;&amp;lt;h1 class=&amp;quot;post-title&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;nav class=&amp;quot;top&amp;quot;&amp;gt;&lt;/code&gt; a better way is &lt;code&gt;&amp;lt;nav class=&amp;quot;main&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;li class=&amp;quot;border-bottom&amp;quot;&amp;gt;&lt;/code&gt; a better way is &lt;code&gt;&amp;lt;li class=&amp;quot;selected&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Class names shouldn’t be design dependent, but specific to content. A text header won’t always be blue, but it will always be the site name. It also makes it easier to read your HTML code  3 months later and not be confussed about what is what.&lt;/p&gt;
&lt;p&gt;Best practice is to never use, colours, spacing, marking, etc. as class names. Only generic names that are independent of how the layout and design looks like.&lt;/p&gt;
&lt;p&gt;A basic weblog homepage can look like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;meta&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;time&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;datetime&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2025-12-26T19:00&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; December 26, 2025 &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;category&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;HTML&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;post-title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://www.htmhell.dev&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;How to HTML&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;intro&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            voluptate velit esse cillum dolore eu fugiat nulla pariatur.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https:/www.htmhell.dev/adventcalendar/2025/26/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;read-more&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        Read more &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;visually-hidden&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            about “How to HTML”&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above HTML example is completely design and layout neutral. The layout and design can be edited only with CSS without having to change things in the HTML.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Keep your class and variable names generic. You want to avoid having to go through all your HTML and CSS code to change names to keep the code readable. There is nothing more painful than having to come back after each design or layout edit and be at lost what is what because &lt;code&gt;&amp;lt;h1 class=&amp;quot;serif-text-header-blue&amp;quot;&amp;gt;&lt;/code&gt; is not blue any more, but a sans font in bright pink.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Abbreviations done right: The &amp;lt;abbr&amp;gt; element and why not use it</title>
    <link href="https://htmhell.dev/adventcalendar/2025/25/"/>
    <updated>2025-12-25T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/25/</id>
    <content type="html">by Alexander Muzenhardt&lt;br&gt;&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Abbreviations are great. They save time and space, make things efficient and tidy, and can even improve readability. But with the wrong technique, these abbreviations can turn into hell when it comes to accessibility.&lt;/p&gt;
&lt;h2 id=&quot;the-perfect-element-for-abbreviations&quot;&gt;The perfect element for abbreviations&lt;/h2&gt;
&lt;p&gt;So, the first thing you do: you look up “abbreviations in HTML” and land straight on MDN (Mozilla Developer Network), at the &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; element. &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; is the short form for abbreviation. The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/abbr&quot;&gt;documentation&lt;/a&gt; shows exactly how to use it properly — and even has an accessibility section. It says that &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; helps people understand what an abbreviation means, especially when it is technical or industry jargon.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;The &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;abbr&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Mozilla Developer Network&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;MDN&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;abbr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; is a documentation repository and learning resource for web developers.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perfect. Exactly what you were looking for. Semantic, accessible — what could go wrong?&lt;br /&gt;
So you start using &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; everywhere. However, after a while you get feedback from people asking what those abbreviations mean &lt;em&gt;and&lt;/em&gt; an accessibility report complaining about … those very same abbreviations.&lt;/p&gt;
&lt;p&gt;Why? According to MDN, you did everything right.&lt;/p&gt;
&lt;h2 id=&quot;the-problem-with-abbr&quot;&gt;The problem with abbr&lt;/h2&gt;
&lt;p&gt;The biggest problem with the &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; element is that its &lt;code&gt;title&lt;/code&gt; attribute behaves completely inconsistently across browsers, and some assistive technologies do not read parts of it at all.&lt;br /&gt;
Adrian Roselli has already run extensive tests on his blog article “&lt;a href=&quot;https://adrianroselli.com/2024/01/using-abbr-element-with-title-attribute.html#Testing&quot;&gt;Using abbr Element with title Attribute&lt;/a&gt;” showing that the &lt;code&gt;title&lt;/code&gt; attribute on &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; elements is not announced by assistive technologies.&lt;/p&gt;
&lt;p&gt;On top of that, the &lt;code&gt;title&lt;/code&gt; attribute is a problem on touch devices — there is simply no way to access it on a smartphone. It only appears on hover, and hover does not exist on touchscreens.&lt;/p&gt;
&lt;p&gt;No matter how you look at it, when you use &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt;, at least one group of users will always miss out on information they need.&lt;/p&gt;
&lt;h2 id=&quot;the-simple-solution-we-are-all-looking-for&quot;&gt;The simple solution we are all looking for&lt;/h2&gt;
&lt;p&gt;The easiest way to make abbreviations accessible is to spell them out the first time they appear, followed by the abbreviation in parentheses or vice versa.&lt;br /&gt;
After that, you can simply use the abbreviation throughout the rest of the text — it’s already been explained once.&lt;/p&gt;
&lt;p&gt;This approach is also accepted by WCAG (Web Content Accessibility Guidelines) 2.2 as a “Sufficient Technique” under “&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Techniques/general/G97&quot;&gt;G97: Providing the first use of an abbreviation immediately before or after the expanded form&lt;/a&gt;”.&lt;br /&gt;
And the best part: you do not even need to touch your HTML markup — you just make your text a bit clearer.&lt;/p&gt;
&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;
&lt;h4&gt;First example&lt;/h4&gt;
&lt;p&gt;In this example, the abbreviation comes first, followed by its full meaning in parentheses.&lt;br /&gt;
&amp;quot;The WAI (Web Accessibility Initiative) demonstrates the W3C (World Wide Web Consortium) commitment to accessibility.&amp;quot;&lt;/p&gt;
&lt;h4&gt;Second example&lt;/h4&gt;
&lt;p&gt;The reverse is equally correct and accessible.&lt;br /&gt;
&amp;quot;The United Nations High Commissioner for Human Rights (UNHCR) was established in 1950 to provide protection and assistance to refugees.&amp;quot;&lt;/p&gt;
&lt;p&gt;The key is consistency: do not switch between the two styles on the same website. Pick one and stick with it.&lt;/p&gt;
&lt;h2 id=&quot;the-alternatives-you-may-need&quot;&gt;The alternatives you may need&lt;/h2&gt;
&lt;p&gt;Below are three possible alternatives. They vary in complexity, and when implementing them, accessibility should always remain a priority. This is especially true for the third option — a dictionary search — where the input field and surrounding UI also need to be accessible.&lt;/p&gt;
&lt;p&gt;I am intentionally leaving out implementation details here, as they would go beyond the scope of this article. These examples rely on other WCAG techniques that are not directly related to abbreviations. You will find plenty of examples online — and if you have questions about any of these approaches, feel free to reach out.&lt;/p&gt;
&lt;h3 id=&quot;linking-to-definitions&quot;&gt;Linking to definitions&lt;/h3&gt;
&lt;p&gt;Of course, spelling out abbreviations is not the only option. You can also link an abbreviation to a page that explains it in detail. There are several ways to do this, all clearly outlined in “&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Techniques/general/G55&quot;&gt;G55: Linking to definitions&lt;/a&gt;”.&lt;/p&gt;
&lt;h3 id=&quot;providing-a-glossary&quot;&gt;Providing a glossary&lt;/h3&gt;
&lt;p&gt;Another option is to provide an internal or external glossary that lists and explains all abbreviations used on your website. You can either link to it or simply reference it when abbreviations appear.&lt;br /&gt;
Just like in books, glossaries can live at the end of a site or section — and readers can look up terms as needed.&lt;br /&gt;
A clear explanation of this approach can be found under “&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Techniques/general/G62&quot;&gt;G62: Providing a glossary&lt;/a&gt;”.&lt;/p&gt;
&lt;h3 id=&quot;providing-a-function-to-search-an-online-dictionary&quot;&gt;Providing a function to search an online dictionary&lt;/h3&gt;
&lt;p&gt;A more elegant approach is to include a search feature on your site that queries an online dictionary for abbreviations and displays relevant results.&lt;br /&gt;
You can find more information on this technique in “&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Techniques/general/G70&quot;&gt;G70: Providing a function to search an online dictionary&lt;/a&gt;”.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Skip the &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; element altogether.&lt;br /&gt;
Right now, it does not add any real value — it only creates a false sense that your abbreviations are truly accessible and understandable by all persons.&lt;/p&gt;
&lt;p&gt;The best and by far simplest solution is to clearly spell out each abbreviation the first time you use it, and then stick to the short form for the rest of the text.&lt;/p&gt;
&lt;p&gt;Cheers&lt;br /&gt;
Alex&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://adrianroselli.com/2024/01/using-abbr-element-with-title-attribute.html&quot;&gt;Using abbr Element with title Attribute&lt;/a&gt; - by Adrian Roselli&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://heydonworks.com/article/the-abbr-element/#main&quot;&gt;THE ABBR ELEMENT&lt;/a&gt; - by Heydon Pickering&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stolperfrei.digital/html-abbr-tag/&quot;&gt;The HTML abbr-tag – Managing Abbreviations the Right Way (German)&lt;/a&gt; - by Ria Weyprecht&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/abbr&quot;&gt;&amp;lt;abbr&amp;gt;: The Abbreviation element&lt;/a&gt; - by mdn&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Understanding/abbreviations.html&quot;&gt;Understanding SC 3.1.4: Abbreviations (Level AAA)&lt;/a&gt; - by W3C&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Techniques/general/G55&quot;&gt;Technique G55: Linking to definitions&lt;/a&gt; - by W3C&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Techniques/general/G62&quot;&gt;Technique G62: Providing a glossary&lt;/a&gt; - by W3C&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Techniques/general/G70&quot;&gt;Technique G70: Providing a function to search an online dictionary&lt;/a&gt; - by W3C&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Techniques/general/G97&quot;&gt;Technique G97: Providing the first use of an abbreviation immediately before or after the expanded form&lt;/a&gt; - by W3C&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>The three semantics of HTML</title>
    <link href="https://htmhell.dev/adventcalendar/2025/24/"/>
    <updated>2025-12-24T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/24/</id>
    <content type="html">by Tomasz Jakut&lt;br&gt;&lt;p&gt;There is always that one elephant in the room alongside HTML – &lt;em&gt;semantics&lt;/em&gt;. You can ignore it for quite a while, but at the end of the day, you&#39;ll need to acknowledge that it&#39;s there, cluttering half of the space.&lt;/p&gt;
&lt;h2 id=&quot;our-beloved-elephant&quot;&gt;Our beloved elephant&lt;/h2&gt;
&lt;p&gt;So let&#39;s examine this exotic beast! According to Longman Dictionary of Contemporary English, &lt;a href=&quot;https://www.ldoceonline.com/dictionary/semantics&quot;&gt;semantics is &lt;q&gt;the meaning of a word or expression&lt;/q&gt;&lt;/a&gt;. In our case, a word is an HTML element. And how can we check what the meaning of a word is? Well, we&#39;ve already done that – we&#39;ve checked the semantics of the semantics (inception!). Fortunately, there is also a dictionary for HTML – it&#39;s called &lt;a href=&quot;https://html.spec.whatwg.org/multipage/&quot;&gt;&lt;cite&gt;HTML Living Standard&lt;/cite&gt;&lt;/a&gt;. It even &lt;a href=&quot;https://html.spec.whatwg.org/multipage/dom.html#semantics-2&quot;&gt;says it contains meanings&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Elements, attributes, and attribute values in HTML are defined (by this specification) to have certain meanings (semantics).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Detailed descriptions of all HTML elements are in &lt;a href=&quot;https://html.spec.whatwg.org/multipage/#toc-semantics&quot;&gt;chapter 4, called &lt;cite&gt;The elements of HTML&lt;/cite&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; That&#39;s why I&#39;m not keen on the &lt;q&gt;semantic elements&lt;/q&gt; concept. For me, they are all semantic – even &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; – since their meanings are described in the specification.&lt;/p&gt;
&lt;p&gt;But what if I told you there are actually three elephants in the room?&lt;/p&gt;
&lt;h2 id=&quot;first-semantics-for-users&quot;&gt;First semantics: for users&lt;/h2&gt;
&lt;p&gt;This is the most straightforward one of them all. That&#39;s the most basic role of semantics: to provide the end user with all the information necessary to correctly understand the content.&lt;/p&gt;
&lt;p&gt;This type of semantics can be compared to formatting a text document in Word. You can always select some text and make it bigger and bolder, pretending it&#39;s a heading. But then you won&#39;t be able to generate a Table of Contents for your document with 100+ pages. The same is true for HTML – except it&#39;s the user that will suffer. Let&#39;s look at an example – my short bio:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Comandeer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;comandeer.avif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Proud HTML Expert&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s still &amp;quot;semantic HTML&amp;quot; (because every HTML element has a meaning!), yet it&#39;s not especially useful. And yes, we can style it in any imaginable way (I bet we can even make it do the &lt;a href=&quot;https://en.wikipedia.org/wiki/Can-can&quot;&gt;can-can&lt;/a&gt; with a bit of CSS magic) – but it&#39;s still just a bunch of &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s &lt;a href=&quot;https://html.spec.whatwg.org/multipage/grouping-content.html#the-div-element&quot;&gt;without any intrinsic meaning&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;div&lt;/code&gt; element has no special meaning at all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Just like this big, bold text in Word – if it&#39;s not a heading, it&#39;s not a heading.&lt;/p&gt;
&lt;p&gt;Let&#39;s focus on raw HTML, forgetting about CSS. If we load the above code in the browser, it will look like this:&lt;/p&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/24/html-div.png&quot; alt=&quot;&amp;quot;Comandeer&amp;qout; is followed by a logo and &amp;qout;Proud HTML Expert&amp;quot; – all text is unstyled.&quot; /&gt;
&lt;p&gt;It&#39;s plain text. And in terms of HTML semantics, that&#39;s the truth – we used all these HTML elements to mark up plain text. Good job!&lt;/p&gt;
&lt;p&gt;Fortunately, it can be easily fixed:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Comandeer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;comandeer.avif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A photo of a smiling Comandeer.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Proud HTML Expert&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;The wrapper &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element was replaced with the &lt;a href=&quot;https://html.spec.whatwg.org/multipage/sections.html#the-article-element&quot;&gt;&lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; one&lt;/a&gt; – a bio can be treated as a &lt;q&gt;complete, or self-contained, composition in a document&lt;/q&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element with my name was replaced with the &lt;a href=&quot;https://html.spec.whatwg.org/multipage/sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element&lt;/a&gt; to indicate the purpose of the &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The image got a &lt;a href=&quot;https://html.spec.whatwg.org/multipage/images.html#alt&quot;&gt;descriptive &lt;code&gt;alt&lt;/code&gt; attribute&lt;/a&gt;, describing its content.&lt;/li&gt;
&lt;li&gt;The last &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; was replaced with the &lt;a href=&quot;https://html.spec.whatwg.org/multipage/grouping-content.html#the-p-element&quot;&gt;&lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; element&lt;/a&gt; – after all, it&#39;s a paragraph of text.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we open the document in the browser, it looks &lt;em&gt;better&lt;/em&gt;:&lt;/p&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/24/html-article.png&quot; alt=&quot;The &amp;quot;Comandeer&amp;quot; is now bigger and bolder, indicating that it is a heading and the &amp;quot;Proud HTML Expert&amp;quot; got a margin around itself.&quot; /&gt;
&lt;p&gt;In other words, we &lt;em&gt;formatted&lt;/em&gt; our text!&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; Each HTML element has its own &lt;a href=&quot;https://html.spec.whatwg.org/multipage/rendering.html#rendering&quot;&gt;default styles&lt;/a&gt;, used to display it when there are no stylesheets provided by the website owner. This is the purest achievable form of HTML in a browser.&lt;/p&gt;
&lt;p&gt;But it isn&#39;t particularly useful on its own. After all, there&#39;s always some CSS to make things prettier – why should we care about choosing appropriate HTML elements? Because the Web should not be only visual. One of the main principles of Web Content Accessibility Guidelines (WCAG) is &lt;a href=&quot;https://w3c.github.io/wcag/guidelines/22/#perceivable&quot;&gt;&lt;q&gt;Perceivable&lt;/q&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Information and user interface components must be presentable to users in ways they can perceive.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, if someone can&#39;t perceive visual information, it &lt;strong&gt;must&lt;/strong&gt; be available for them in another form. A bunch of styled &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s do not convey any meaning without their visuals. And that&#39;s problematic for assistive technology, like &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Screen_reader&quot;&gt;screen readers&lt;/a&gt;. Screen readers use an &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Accessibility_tree&quot;&gt;accessibility tree&lt;/a&gt; – a DOM-like structure, built from the page&#39;s HTML and containing information about roles and purposes of all HTML elements. Let&#39;s see what that tree looks like for the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; version of the page:&lt;/p&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/24/a11y-div.png&quot; alt=&quot;Both &amp;quot;Comandeer&amp;quot; and &amp;quot;Proud HTML Expert&amp;quot; are marked up as static text.&quot; /&gt;
&lt;p&gt;It&#39;s just a text. More importantly, the image is missing, due to its empty &lt;code&gt;alt&lt;/code&gt; attribute. The &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; version is much better:&lt;/p&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/24/a11y-article.png&quot; alt=&quot;The whole bio is wrapped in the article, the &amp;quot;Comandeer&amp;quot; is correctly identified as a heading, the image has a description of &amp;quot;A photo of smiling Comandeer&amp;quot; and the &amp;quot;Proud HTML Expert&amp;quot; is marked up as a paragraph.&quot; /&gt;
&lt;p&gt;Thanks to that, the screen reader can successfully transform the page content into voice or braille and inform the user where the articles, headings, and other elements are. It would not only allow the user to fully understand the page (similarly to how the non-screen-reader user perceived the visual version of the page) but also allow the screen reader to provide better ways of navigating the page, e.g., by &lt;a href=&quot;https://webaim.org/projects/screenreadersurvey10/#finding&quot;&gt;jumping to headings&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In other words, caring about semantics is caring for the user!&lt;/p&gt;
&lt;h2 id=&quot;second-semantics-for-user-agents&quot;&gt;Second semantics: for user agents&lt;/h2&gt;
&lt;p&gt;Semantics can also be used to provide additional information for user agents. And I deliberately use this term in quite a wide meaning, to mean any machine or software acting on behalf of its user. The most obvious example of a user agent is a browser (which is the term&#39;s typical meaning), but I would extend that name also to search engines. With a long history of &lt;a href=&quot;https://en.wikipedia.org/wiki/Search_engine_optimization&quot;&gt;SEO (Search Engine Optimization)&lt;/a&gt;, it&#39;s not a mystery that search engines can and &lt;em&gt;do&lt;/em&gt; understand HTML – just to mention everlasting discussions about the importance of heading elements. Also, browsers can use semantics to provide affordances for users, like &lt;a href=&quot;https://medium.com/@mandy.michael/building-websites-for-safari-reader-mode-and-other-reading-apps-1562913c86c9&quot;&gt;using the &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; element to extract content in a reader mode&lt;/a&gt;. But there are also other ways to provide yet another layer of semantics just for machines.&lt;/p&gt;
&lt;p&gt;The most ambitious take on semantics for user agents is Web 3.0. And no, I don&#39;t mean Web3, based on blockchain. Long before that, back in the 2000s, W3C imagined a new type of web, as they called it – &lt;a href=&quot;https://www.w3.org/2007/Talks/0123-sb-W3CEmergingTech/Overviewp.pdf&quot;&gt;Web of Data and Services, aka Semantic Web&lt;/a&gt;. The idea itself was quite simple yet ingenious: the Web is full of data, but there was no way to enable effective communication between different websites and apps. Back then, machines were also far worse at discovering and understanding data. So they needed us, humans, to &lt;em&gt;mark up&lt;/em&gt; data for them. The most basic way of marking stuff up is using HTML. But several additional technologies were developed to allow embedding additional metadata into websites. One of the first was &lt;a href=&quot;https://www.w3.org/RDF/&quot;&gt;Resource Description Framework (RDF)&lt;/a&gt;. It&#39;s a &lt;em&gt;huge&lt;/em&gt; standard, divided into several specifications. Yet it has one, pretty serious, downside: it&#39;s not built on top of HTML, as it has its own syntaxes (yes, plural). That&#39;s why &lt;a href=&quot;https://rdfa.info/&quot;&gt;RDFa&lt;/a&gt; has been developed. It&#39;s a &amp;quot;lighter&amp;quot; version of RDF and can be used inside HTML via attributes:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;vocab&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://schema.org/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Person&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Comandeer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;comandeer.avif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A photo of a smiling Comandeer.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Proud &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;jobTitle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;HTML Expert&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;vocab&lt;/code&gt; attribute points to the vocabulary we want to use and the &lt;code&gt;typeof&lt;/code&gt; one – a type of data we try to mark up. In our example, we want to spice up my bio with some additional metadata. Due to that, we decided to use the &lt;code&gt;Person&lt;/code&gt; type (as I&#39;m personally a person). Each property of, well, &lt;em&gt;me&lt;/em&gt; is marked up with the &lt;code&gt;property&lt;/code&gt; attribute, e.g., the heading with the name now has the &lt;code&gt;property=&amp;quot;name&amp;quot;&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;But of course, &lt;a href=&quot;https://xkcd.com/927/&quot;&gt;there is always more than one way to do something&lt;/a&gt;. HTML has its own way of marking up additional metadata, so-called &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Microdata&quot;&gt;microdata&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemscope&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemtype&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://schema.org/Person&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Comandeer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;comandeer.avif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A photo of a smiling Comandeer.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Proud &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;jobTitle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;HTML Expert&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s pretty similar to RDFa. Instead of &lt;code&gt;vocab&lt;/code&gt; + &lt;code&gt;typeof&lt;/code&gt; attributes, it uses &lt;code&gt;itemscope&lt;/code&gt; + &lt;code&gt;itemtype&lt;/code&gt; ones, and the &lt;code&gt;property&lt;/code&gt; one is replaced with &lt;code&gt;itemprop&lt;/code&gt; one.&lt;/p&gt;
&lt;p&gt;And if we want something more like RDF (so a separate thing from HTML), there is always &lt;a href=&quot;https://json-ld.org/&quot;&gt;JSON-LD&lt;/a&gt; – a way to express metadata in JSON. I also need to make one honorable mention – &lt;a href=&quot;https://microformats.io/&quot;&gt;microformats&lt;/a&gt;. They are the OGs of metadata in HTML. They use the &lt;code&gt;class&lt;/code&gt; attribute to provide additional info about the content:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;h-card&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;p-name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Comandeer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;comandeer.avif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;u-photo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A photo of a smiling Comandeer.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Proud &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;p-job-title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;HTML Expert&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;https://microformats.org/wiki/h-card&quot;&gt;hCard microformat&lt;/a&gt; is used for marking up information about people. What I love about microformats is the fact that they are Just HTML™ without any fancy attributes.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; Personally, I&#39;m a fan of the RDFa format, so I&#39;ll stick to it for the rest of the article.&lt;/p&gt;
&lt;p&gt;But what are vocabularies? In short, they are catalogs of things that can be described, like people, events, books, and places. Each of these things has its own unique set of properties (people have names, places have addresses, events have dates…). Things can also be mixed together (events are organized by people, etc.). Thanks to that, even more complex pieces of reality can be described in a manner understandable by machines.&lt;/p&gt;
&lt;p&gt;In our example, the &lt;a href=&quot;https://schema.org/&quot;&gt;Schema.org&lt;/a&gt; vocabulary is used. &lt;a href=&quot;http://schema.org/&quot;&gt;Schema.org&lt;/a&gt; is a community effort, founded by Google, Microsoft, Yahoo, and Yandex, with a goal to create an open standard for structured data on the Web. This data is then used by search engines to provide additional information about the websites&#39; content. &lt;a href=&quot;https://developers.google.com/search/docs/appearance/structured-data/search-gallery&quot;&gt;Google provides a gallery&lt;/a&gt; of how it uses the structured data to prepare more detailed search results.&lt;/p&gt;
&lt;p&gt;The only problem with Web 3.0 is that it never happened. Granted, we have several great technologies to embed additional metadata. But at the end of the day, they&#39;re used mainly by search engines. The ambitious vision of the Web where machines talk to each other and exchange data to provide better services to their users is still just a vision.&lt;/p&gt;
&lt;h2 id=&quot;third-semantics-for-web-developers&quot;&gt;Third semantics: for web developers&lt;/h2&gt;
&lt;p&gt;And finally, we can leave the vast land of user-centered semantics and enter the cozy territory of developer-centered semantics. Because an easily understandable HTML is also an easily maintainable HTML. And if we use HTML elements as intended (like creating lists with &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; elements instead of &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s), we&#39;re already halfway there!&lt;/p&gt;
&lt;p&gt;But sometimes additional info is needed, e.g., a page contains several &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; elements and we want to easily distinguish between them. In that case, we can go back to webdev roots and use the &lt;code&gt;class&lt;/code&gt; attribute.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;vocab&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://schema.org/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Person&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;bio&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;bio__name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Comandeer&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;comandeer.avif&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A photo of a smiling Comandeer.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;bio__image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;bio__description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Proud &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;jobTitle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;bio__job-title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;HTML Expert&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;m using a &lt;a href=&quot;https://getbem.com/&quot;&gt;BEM-like&lt;/a&gt; naming convention here to indicate that this particular &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; is a bio. Each of the elements inside the &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; also has its own class name, indicating its purpose.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; It can be argued that most of these classes are redundant, repeating the information already provided by RDFa. Yet I tend to treat BEM not as a naming convention but as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Domain-specific_language&quot;&gt;DSL (Domain Specific Language)&lt;/a&gt; for creating component-based applications. However, that&#39;s a story for another time.&lt;/p&gt;
&lt;p&gt;There are also other ways to make HTML more developer-friendly. One of the better (at least in my opinion) is to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements&quot;&gt;use custom elements&lt;/a&gt; to replace plain old &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;card&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- vs --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;the-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;the-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We would also need to add a little bit of CSS:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:not(:defined)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It ensures that custom elements are displayed as block elements (that is, like &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s) because by default, they’re displayed inline (like &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;s).&lt;/p&gt;
&lt;h2 id=&quot;fourth-semantics?&quot;&gt;Fourth semantics?&lt;/h2&gt;
&lt;p&gt;Yet another elephant looms on the horizon… There is no doubt that we live in the AI era. &lt;a href=&quot;https://en.wikipedia.org/wiki/Large_language_model&quot;&gt;LLMs (Large Language Models)&lt;/a&gt; are everywhere around us, and they are yet another kind of machine that can understand HTML. But hey, they are &lt;em&gt;language models&lt;/em&gt;, finally our technology has advanced enough to be able to fully grasp the beauty of Web 3.0!&lt;/p&gt;
&lt;p&gt;Except it doesn&#39;t seem to be the case. Instead of using what we already have, new standards emerge [insert XKCD strip about standards here]. The most popular of them is the &lt;a href=&quot;https://llmstxt.org/&quot;&gt;&lt;code&gt;/llms.txt&lt;/code&gt; file&lt;/a&gt;. It&#39;s a Markdown file containing detailed instructions for LLMs on how to handle the website and where particular info is located.&lt;/p&gt;
&lt;p&gt;It’s quite ironic that after years of striving toward a semantic Web, we finally have &lt;em&gt;the&lt;/em&gt; technology capable of understanding it - and it still doesn’t work. Oh, well, maybe in another 20 years…&lt;/p&gt;
&lt;p&gt;However, there is a glimpse of change! OpenAI recently released their AI browser, Atlas. Supposedly, it &lt;a href=&quot;https://help.openai.com/en/articles/12627856-publishers-and-developers-faq#h_9910e2a408&quot;&gt;understands ARIA&lt;/a&gt;. In theory, the more accessible a site is, the more it&#39;s suitable for ChatGPT. In practice, it could &lt;a href=&quot;https://adrianroselli.com/2025/10/openai-aria-and-seo-making-the-web-worse.html&quot;&gt;make the Web far worse&lt;/a&gt;. ARIA should be the last resort when &lt;a href=&quot;https://w3c.github.io/using-aria/#rule1&quot;&gt;native HTML is not enough&lt;/a&gt; to express a complex UI pattern. Adding it solely to &lt;em&gt;impress&lt;/em&gt; a machine sounds disturbingly similar to an ancient arcane of stuffing web pages with invisible links to fool &lt;a href=&quot;https://en.wikipedia.org/wiki/Web_crawler&quot;&gt;crawlers&lt;/a&gt;. On the other hand, Atlas&#39;s reliance on ARIA could be a visible symptom of &lt;a href=&quot;https://en.wiktionary.org/wiki/divitis&quot;&gt;The Great Disease of the Web&lt;/a&gt;: LLMs are powerful enough to understand HTML semantics, but there is no semantics to be understood…&lt;/p&gt;
&lt;h2 id=&quot;managing-the-menagerie&quot;&gt;Managing the menagerie&lt;/h2&gt;
&lt;p&gt;Let me ask you a fundamental question: do you pay attention to HTML semantics?&lt;/p&gt;
&lt;p&gt;If the answer is &amp;quot;yes&amp;quot;, then good job, your elephants are happy and thriving 🐘!&lt;/p&gt;
&lt;p&gt;However, if the answer is &amp;quot;no&amp;quot;… Don&#39;t make them sad, find a little bit of time and enhance your HTML. Throw away extraneous &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s, add a couple of headings, embed some metadata! There is no need to do everything at once; do it step by step. Every little improvement matters and can make someone&#39;s day a little better. A screenreader user will be grateful for that additional heading, your fellow web developer will thank you for that extra class, and a crawler… Well, it won&#39;t feel anything, but hey, it will understand your content better!&lt;/p&gt;
&lt;p&gt;If you do not know how to start, I suggest removing all distractions – including CSS – and focusing on the raw content. Copy it to your favourite word processor and think about the &lt;em&gt;role&lt;/em&gt; of each element and its &lt;em&gt;relationship&lt;/em&gt; with other elements. And then format all of them according to your findings. That&#39;s your content&#39;s semantics, waiting to be ported back to HTML!&lt;/p&gt;
&lt;p&gt;Do it, for your users, for your fellow web developers (not necessarily for crawlers…), but most importantly – for the &lt;em&gt;elephants&lt;/em&gt;!&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>For the Love of &amp;lt;details&amp;gt;</title>
    <link href="https://htmhell.dev/adventcalendar/2025/23/"/>
    <updated>2025-12-23T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/23/</id>
    <content type="html">by Justin Ferrell&lt;br&gt;&lt;p&gt;When you list all the things HTML can do out of the box without the help of CSS or Javascript, it can seem like a short list. Headings and lists will come to mind. You will most likely think of things like images and video. Any good list of HTML elements will grow to include form elements like input and select, the original interactive elements, too. Recently, a lot of work and attention has turned to some of the lesser known semantic HTML elements too. The work of &lt;a href=&quot;https://front-end.social/@heydon&quot;&gt;Heydon Pickering&lt;/a&gt; comes to mind, and his incredible effort to explain &lt;a href=&quot;https://heydonworks.com/article/the-col-element/&quot;&gt;every HTML element&lt;/a&gt; in alphabetical order.&lt;/p&gt;
&lt;p&gt;Among the lists and the images and the forms and the videos though, I think there is an unsung hero. There is a piece of semantic markup that exists at the intersection of SEO, accessibility, performance and interactivity.&lt;/p&gt;
&lt;p&gt;I am talking of course about the &amp;lt;details&amp;gt; element and its partner, the &amp;lt;summary&amp;gt; element.&lt;/p&gt;
&lt;h2 id=&quot;lessdetailsgreater-details&quot;&gt;&amp;lt;details&amp;gt; Details&lt;/h2&gt;
&lt;p&gt;For the uninitiated, the &amp;lt;details&amp;gt; element acts as a disclosure widget. When I was getting my start in early 2011, the &amp;lt;details&amp;gt; element would have (incorrectly) been called an accordion if it existed at the time. It consists of an outer &amp;lt;details&amp;gt; element with a &amp;lt;summary&amp;gt; element nested directly beneath it. In its “closed” state, only the &amp;lt;summary&amp;gt; element is visible. When open (with an [open] attribute present on the &amp;lt;details&amp;gt; element) all of the content following the &amp;lt;summary&amp;gt; element is made visible.&lt;/p&gt;
&lt;iframe height=&quot;300&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Basic Demo of &amp;lt;details&amp;gt; &quot; src=&quot;https://codepen.io/developerjustin/embed/OPMzVzX?default-tab=html%2Cresult&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/developerjustin/pen/OPMzVzX&quot;&gt;
  Basic Demo of &amp;lt;details&amp;gt; &lt;/a&gt; by Justin Ferrell (&lt;a href=&quot;https://codepen.io/developerjustin&quot;&gt;@developerjustin&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;The most remarkable thing about the &amp;lt;details&amp;gt; element is that this disclosure functionality requires no dependencies of any kind. It requires zero CSS or Javascript of any kind, is keyboard navigable and accessible out of the box and is widely understood by search engines and web crawlers alike, making it a semantic choice for things like FAQ’s.&lt;/p&gt;
&lt;p&gt;Put simply, &amp;lt;details&amp;gt; is one of the few semantic, interactive elements HTML gives us. That scarcity makes it special.&lt;/p&gt;
&lt;h2 id=&quot;lessdetailsgreater-are-always-in-style&quot;&gt;&amp;lt;details&amp;gt; Are Always in Style&lt;/h2&gt;
&lt;p&gt;If an element gives you so much for free, surely it must fight back when you try to style it, right?&lt;/p&gt;
&lt;p&gt;Not the case!&lt;/p&gt;
&lt;p&gt;The triangle disclosure icon that you see in a &amp;lt;details&amp;gt; element is actually the list-item marker of the &amp;lt;summary&amp;gt; element. In modern browsers, you can target it with the summary::marker pseudo-element. You can change the size, color, icon and even if the symbol is present at all.&lt;/p&gt;
&lt;p&gt;Because the open state of the &amp;lt;details&amp;gt; element is marked using an [open] attribute, it’s possible to target the &amp;lt;details&amp;gt; element, the &amp;lt;summary&amp;gt; element and anything therein just by using an attribute selector.&lt;/p&gt;
&lt;iframe height=&quot;300&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Untitled&quot; src=&quot;https://codepen.io/developerjustin/embed/wBMpayo?default-tab=html%2Cresult&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/developerjustin/pen/wBMpayo&quot;&gt;
  Untitled&lt;/a&gt; by Justin Ferrell (&lt;a href=&quot;https://codepen.io/developerjustin&quot;&gt;@developerjustin&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;And using the &lt;strong&gt;::details-content&lt;/strong&gt; selector, you can target the inner content of the &amp;lt;details&amp;gt; element too! This &lt;strong&gt;::details-content&lt;/strong&gt; selector is particularly powerful when paired with the [open] attribute selector.&lt;/p&gt;
&lt;iframe height=&quot;300&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Untitled&quot; src=&quot;https://codepen.io/developerjustin/embed/YPqrONy?default-tab=html%2Cresult&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot;&gt;
	See the Pen &lt;a href=&quot;https://codepen.io/developerjustin/pen/YPqrONy&quot;&gt;
	Untitled&lt;/a&gt; by Justin Ferrell (&lt;a href=&quot;https://codepen.io/developerjustin&quot;&gt;@developerjustin&lt;/a&gt;)
	on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;Though browser support isn’t perfect, it’s even possible to tweak the animation and transition of a &amp;lt;details&amp;gt; element from its open state to its closed state.&lt;/p&gt;
&lt;h2 id=&quot;the-devil-and-the-lessdetailsgreater&quot;&gt;The Devil and the &amp;lt;details&amp;gt;&lt;/h2&gt;
&lt;p&gt;Just like its Cascading Counterpart, Javascript is no stranger to the &amp;lt;details&amp;gt; element.&lt;/p&gt;
&lt;p&gt;The &amp;lt;details&amp;gt; element fires a toggle event when opened or closed. You can attach an event listener to that just like you would with any other element.&lt;/p&gt;
&lt;iframe height=&quot;300&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Scripted &amp;lt;details&amp;gt; Demo&quot; src=&quot;https://codepen.io/developerjustin/embed/dPGJodx?default-tab=html%2Cresult&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/developerjustin/pen/dPGJodx&quot;&gt;
  Scripted &amp;lt;details&amp;gt; Demo&lt;/a&gt; by Justin Ferrell (&lt;a href=&quot;https://codepen.io/developerjustin&quot;&gt;@developerjustin&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;To really get at what makes the &amp;lt;details&amp;gt; element tick though, you can always set the open property of the element to true/false to open or close the widget respectively.&lt;/p&gt;
&lt;iframe height=&quot;300&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Toggle &amp;lt;details&amp;gt; Demo&quot; src=&quot;https://codepen.io/developerjustin/embed/emJyNMK?default-tab=html%2Cresult&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/developerjustin/pen/emJyNMK&quot;&gt;
  Toggle &amp;lt;details&amp;gt; Demo&lt;/a&gt; by Justin Ferrell (&lt;a href=&quot;https://codepen.io/developerjustin&quot;&gt;@developerjustin&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;h2 id=&quot;prevails-through-lessdetailsgreater&quot;&gt;Prevails Through &amp;lt;details&amp;gt;&lt;/h2&gt;
&lt;p&gt;The power of &amp;lt;details&amp;gt; does not stop with how you can style it and how you can interact with it via Javascript. The &amp;lt;details&amp;gt; element has additional capabilities via good old HTML that are arguably more powerful than anything you can do it with Javascript.&lt;/p&gt;
&lt;h3 id=&quot;deeping-linking&quot;&gt;Deeping Linking&lt;/h3&gt;
&lt;p&gt;A handy feature of most modern browsers (looking at you, &lt;a href=&quot;https://frontendmasters.com/blog/opening-a-details-element-from-the-url/&quot;&gt;Safari&lt;/a&gt;) is that navigating to an anchor or fragment inside a closed &amp;lt;details&amp;gt; will automatically open it so the user can see the target.&lt;/p&gt;
&lt;p&gt;Remarkably, on-page search supports the &amp;lt;details&amp;gt; element too! Browsers support varies but in most modern browsers, traditional &amp;quot;Command/Control + F&amp;quot; search will query the contents of the &amp;lt;details&amp;gt; element and expand them as needed.&lt;/p&gt;
&lt;iframe height=&quot;300&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Untitled&quot; src=&quot;https://codepen.io/developerjustin/embed/wBMpajg?default-tab=html%2Cresult&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/developerjustin/pen/wBMpajg&quot;&gt;
  Untitled&lt;/a&gt; by Justin Ferrell (&lt;a href=&quot;https://codepen.io/developerjustin&quot;&gt;@developerjustin&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;h3 id=&quot;exclusivity&quot;&gt;Exclusivity&lt;/h3&gt;
&lt;p&gt;Details elements support a name attribute to group them into an exclusive set (like radio buttons).  If multiple &amp;lt;details&amp;gt; share the same name, opening one will automatically close any others in that group.&lt;/p&gt;
&lt;iframe height=&quot;300&quot; style=&quot;width: 100%;&quot; scrolling=&quot;no&quot; title=&quot;Exclusive &amp;lt;details&amp;gt; Demo&quot; src=&quot;https://codepen.io/developerjustin/embed/KwVZpey?default-tab=html%2Cresult&quot; frameborder=&quot;no&quot; loading=&quot;lazy&quot; allowtransparency=&quot;true&quot; allowfullscreen=&quot;true&quot;&gt;
  See the Pen &lt;a href=&quot;https://codepen.io/developerjustin/pen/KwVZpey&quot;&gt;
  Exclusive &amp;lt;details&amp;gt; Demo&lt;/a&gt; by Justin Ferrell (&lt;a href=&quot;https://codepen.io/developerjustin&quot;&gt;@developerjustin&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.
&lt;/iframe&gt;
&lt;p&gt;It&#39;s worth flagging the potential for &lt;a href=&quot;https://yatil.net/blog/exclusive-accordions&quot;&gt;accessibility issues&lt;/a&gt; related to this feature. Exclusive &amp;lt;details&amp;gt; elements are more likely to cause a higher cognitive load and make the comparison of details more difficult. Exclusive &amp;lt;details&amp;gt; elements are by nature more complicated to use with a keyboard and may also cause issues with visibility and screen readers.&lt;/p&gt;
&lt;h2 id=&quot;&amp;quot;but-her-lessdetailsgreater!&amp;quot;&quot;&gt;&amp;quot;But her &amp;lt;details&amp;gt;!&amp;quot;&lt;/h2&gt;
&lt;p&gt;In 2025, &amp;lt;details&amp;gt; is well supported across major browsers, though some versions of Safari still have quirks like not auto-opening on anchor links. It’s pretty unlikely that you’ll run into meaningful issues but it’s always good to see what browsers your users are using.&lt;/p&gt;
&lt;h2 id=&quot;in-lesssummarygreater&quot;&gt;In &amp;lt;summary&amp;gt;&lt;/h2&gt;
&lt;p&gt;While humble on the surface, the &amp;lt;details&amp;gt; element is an untapped treasure trove of interactivity. It can do so much out of the box but paired with some creative HTML and CSS, it’s easy to imagine dozens of uses for the &amp;lt;details&amp;gt; element that do not compromise on performance, accessibility or SEO visibility.&lt;/p&gt;
&lt;p&gt;Here are 6 not-so-real world examples with a focus on accessibility and SEO.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Frequently Asked Questions (FAQs):&lt;/strong&gt; This really is the gold standard for this element. It can help keep pages tidy while ensuring the content is fully indexable by search engines and completely accessible to screen readers without complex ARIA attributes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Video &amp;amp; Audio Transcripts:&lt;/strong&gt; A massive SEO and accessibility win. &amp;lt;details&amp;gt; allows you to include the full text of a podcast or video for keyword indexing and hearing-impaired users, without forcing users to scroll past a massive wall of text to reach the footer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Product Specification Tables:&lt;/strong&gt; &amp;lt;details&amp;gt; allows you to hide dense, technical rows (dimensions, materials, voltages) that are crucial for technical SEO rankings but visually overwhelming for the average shopper.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Table of Contents:&lt;/strong&gt; Placing a collapsible &amp;quot;On this page&amp;quot; navigation widget at the top (or sticky side) of long articles helps bots understand page structure and helps users jump to relevant sections immediately.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Long-form Content &amp;quot;TL;DR&amp;quot;:&lt;/strong&gt; Placing an Executive Summary at the very top of a long article that expands for the full breakdown. This improves &amp;quot;Time on Page&amp;quot; metrics by letting users get the gist immediately rather than bouncing because the article looks too long.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expanded Author Bios:&lt;/strong&gt; Enhance your E-E-A-T (Experience, Expertise, Authoritativeness, and Trustworthiness) signals by including full credentials, past work, and social links in a bio that expands, rather than just a simple name and photo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope you find even more uses for &amp;lt;details&amp;gt; in your own work!&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>The HTML Elements Time Forgot</title>
    <link href="https://htmhell.dev/adventcalendar/2025/22/"/>
    <updated>2025-12-22T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/22/</id>
    <content type="html">by Declan Chidlow&lt;br&gt;&lt;p&gt;Last year I inflicted upon you the cursed knowledge of &lt;a href=&quot;https://htmhell.dev/adventcalendar/2024/20/&quot;&gt;HTML&#39;s legacy colour parsing&lt;/a&gt;, a crime for which I&#39;m still yet to pay. This year, I return with more unwanted and unrequested HTML knowledge of yore.&lt;/p&gt;
&lt;p&gt;The truth is, HTML is getting old, folks. The initial release was 1993, 32 years ago. It certainly isn&#39;t decrepit, but it does have a storied past – a couple of missteps, tabloid scandals, and unflattering paparazzi photos. That&#39;s why I&#39;m so glad you&#39;re joining us here today to peruse some of these bad haircuts of HTML&#39;s youth.&lt;/p&gt;
&lt;p&gt;In the HTML Living Standard there are explicit considerations for what are called &lt;a href=&quot;https://html.spec.whatwg.org/multipage/obsolete.html#non-conforming-features&quot;&gt;non-conforming features&lt;/a&gt;. To quote the standard, &lt;q&gt;Elements in the following list are entirely obsolete, and must not be used by authors&lt;/q&gt;. Thus, I shall issue the disclaimer not to use these lest WHATWG show up at my door.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;marquee&amp;gt;&lt;/code&gt; is perhaps the most famous of all, second only to &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt;, which was never standardised. Daniela Kubesch &lt;a href=&quot;https://www.htmhell.dev/adventcalendar/2022/15/&quot;&gt;wrote about the &lt;code&gt;marquee&lt;/code&gt; tag and implementing it in a modern way&lt;/a&gt; previously, so I&#39;ll leave that to them.&lt;/p&gt;
&lt;p&gt;But there are far more obscure tags which are perhaps less visually dazzling but equally or even more interesting. If you&#39;re younger, this might very well be your introduction to them. If you&#39;re older, this still might be an introduction, but also possibly a trip down memory lane or a flashback to the horrors of the first browser war. It depends.&lt;/p&gt;
&lt;h2 id=&quot;bgsound&quot;&gt;bgsound&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;bgsound&amp;gt;&lt;/code&gt; was a way to play sound in the background, because everyone loves web pages making sounds they didn&#39;t ask for at them. It was not standardised, and exclusively part of Internet Explorer. The &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; tag is the much more courteous modern equivalent.&lt;/p&gt;
&lt;p&gt;I find it endlessly humorous that the old HTML Wiki&#39;s &lt;a href=&quot;https://www.w3.org/html/wiki/Elements/bgsound#Examples&quot;&gt;example section for the tag&lt;/a&gt; simply states, &#39;No, really. Don&#39;t use it.&#39;. Many of the old and obscure elements share the same detail.&lt;/p&gt;
&lt;h2 id=&quot;framesets&quot;&gt;Framesets&lt;/h2&gt;
&lt;p&gt;In the olden days, people used &#39;frames&#39;. Not iframes mind you, just frames. You can think of their usage vaguely like the HTML imports we have now... Wait, what do you mean we still don&#39;t have HTML imports?&lt;/p&gt;
&lt;p&gt;I digress. This was a time long before single-page applications (SPAs) or anything of that nature. Frames were widely used as a way to aid navigation without needing to reload the page. You could have a navigation frame that persisted while the content frame changed.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;frame&amp;gt;&lt;/code&gt; is more or less the same as our modern &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;, though we use iframes much more for embedding than page layout. &lt;code&gt;&amp;lt;frameset&amp;gt;&lt;/code&gt; holds these frames, so you could write something like &lt;code&gt;&amp;lt;frameset cols=&amp;quot;50%, 50%&amp;quot;&amp;gt;&lt;/code&gt; to have two frames next to each other.&lt;/p&gt;
&lt;p&gt;The frameset approach had quite a few problems. Accessibility was really poor, and because everything was a single page, it could be hard to link to a specific section. &lt;s&gt;Thankfully we&#39;ve come a long way since then, and developers take great care with accessibility and ensuring their SPAs respect the web platform.&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;Similarly to how &lt;code&gt;&amp;lt;noscript&amp;gt;&lt;/code&gt; is triggered if JavaScript isn&#39;t supported, &lt;code&gt;&amp;lt;noframes&amp;gt;&lt;/code&gt; allows you to set content if frames aren&#39;t supported.&lt;/p&gt;
&lt;p&gt;While they absolutely shouldn&#39;t be used anymore, unlike much of what this article covers, frames and framesets are still supported. They may have been deprecated in HTML5, but the web&#39;s backward compatibility keeps them going.&lt;/p&gt;
&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; aren&#39;t strangers to us. We&#39;re good friends, no matter the horrific scripts we may force them to hold. However, pre-&lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; there were plenty of other implementations in the wind.&lt;/p&gt;
&lt;p&gt;The e&lt;strong&gt;x&lt;/strong&gt;a&lt;strong&gt;mp&lt;/strong&gt;le element, &lt;code&gt;&amp;lt;xmp&amp;gt;&lt;/code&gt;, is like our modern &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;, but doesn&#39;t interpret special characters like &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, or &lt;code&gt;&amp;amp;&lt;/code&gt;. With &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;, we often need to escape these values to avoid Unwanted Shenanigans™.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;listing&amp;gt;&lt;/code&gt; is yet another step in presenting code on a page. It aimed to display text exactly as the author wrote it, preserving whitespace and formatting, but never got proper support and became obsolete with HTML5. Modern browsers handle it the same as &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; is a funny one. It does what it says on the tin – that is, tells the browser to interpret everything after it as plain text. Of course, this means that any potential closing tag is &lt;em&gt;also&lt;/em&gt; interpreted as plain text and therefore not parsed by the browser. Once opened, you cannot close a &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt;. The rest of the file becomes plaintext for eternity and whatever comes after. It was deprecated in HTML 2 and made invalid in HTML 4, so most modern browsers just interpret it the same as a &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;. The modern approach is to serve content with a MIME type of &lt;code&gt;text/plain&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;spacer&quot;&gt;spacer&lt;/h2&gt;
&lt;p&gt;Before the modern days of flexbox and grid and even floats, we laid things out with tables. Like cavepeople.&lt;/p&gt;
&lt;p&gt;Of course, sometimes with tables, you need a spacer. &lt;code&gt;spacer.gif&lt;/code&gt; used to be popular – a simple 1px × 1px image that could be used to fill a space. But then Netscape got fancy with it and introduced the totally tubular &lt;code&gt;&amp;lt;spacer&amp;gt;&lt;/code&gt; tag. You could write &lt;code&gt;&amp;lt;spacer width=&amp;quot;50&amp;quot; height=&amp;quot;20&amp;quot;&amp;gt;&lt;/code&gt; on your website and get a little element that took up some space.&lt;/p&gt;
&lt;p&gt;Pretty fly, though this was only a stop-gap implementation that didn&#39;t last long and was never standardised.&lt;/p&gt;
&lt;h2 id=&quot;keygen&quot;&gt;keygen&lt;/h2&gt;
&lt;p&gt;I hear keygen, and my mind goes to acquiring a copy of a video game or enterprise software in a less than scrupulous way. That isn&#39;t to say the &lt;code&gt;&amp;lt;keygen&amp;gt;&lt;/code&gt; element had anything to do with software cracking, though, and unfortunately didn&#39;t come with &lt;a href=&quot;https://www.youtube.com/watch?v=0emL2ACcBkk&quot;&gt;sick tunes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It was a way for browsers to generate public-private key pairs for form submissions, primarily used for certificate generation. The idea was to make cryptographic operations easier for users, but in practice, it had security concerns and inconsistent browser support. You can read a little bit of discussion from the time in &lt;a href=&quot;https://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20080714/07ea5534/attachment.txt&quot;&gt;this mailing list thread&lt;/a&gt;. It was deprecated and is now removed from all modern browsers.&lt;/p&gt;
&lt;h2 id=&quot;nextid&quot;&gt;nextid&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;nextid&amp;gt;&lt;/code&gt; comes with the fun trivia of being the first tag to be eliminated from the official public DTD&#39;s of HTML versions. It was used by early HTML editors to generate unique identifiers but quickly became obsolete. It was part of those early days of HTML where the vision wasn&#39;t just viewing but also editing.&lt;/p&gt;
&lt;p&gt;It is a hard element to get much info about, and it seems I&#39;m not alone in thinking that, as the very interesting and well-worth-a-read document &lt;a href=&quot;http://the-pope.com/nextid.html&quot;&gt;Working NEXTID Tag Element Example&lt;/a&gt; has this to say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is also probably one of the least understood of all of the early HTML elements, being poorly documented, not explained in any depth anywhere, and those who obviously understood how it worked couldn&#39;t be bothered to explain it to the rest of us.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;isindex&quot;&gt;isindex&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;isindex&amp;gt;&lt;/code&gt; is a particularly interesting part of the old web because, perhaps more than any other tag shown here, it reflects a very different vision of HTML semantics. It was a way to define a search box that would submit queries directly to the server. You&#39;d write something like:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;isindex prompt=&amp;quot;Enter your search term here:&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This primitive search functionality was eventually superseded by proper form elements, giving developers much more control over how search interfaces worked.&lt;/p&gt;
&lt;h2 id=&quot;dir&quot;&gt;dir&lt;/h2&gt;
&lt;p&gt;I&#39;m talking about &lt;code&gt;&amp;lt;dir&amp;gt;&lt;/code&gt;, not &lt;code&gt;dir&lt;/code&gt; – the element, not the property indicating text direction. The purpose of &lt;code&gt;&amp;lt;dir&amp;gt;&lt;/code&gt; was to serve as a container for files and directories. It wasn&#39;t just your bog-standard list, though, because the user agent could apply different styles and icons depending on the content type.&lt;/p&gt;
&lt;p&gt;You could also give it the attribute &lt;code&gt;compact&lt;/code&gt; to make the content take up less space in an effect similar to setting &lt;code&gt;line-height&lt;/code&gt;. As you might imagine, the modern equivalent is to use a standard list with &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;closing-tags&quot;&gt;Closing Tags&lt;/h2&gt;
&lt;p&gt;It is easy for us to look back from the year of our lord &lt;code title=&quot;Don&#39;t you dare send me an email about this.&quot;&gt;${new Date().getFullYear()}&lt;/code&gt; and ridicule what obviously wasn&#39;t to be, but these stumblings have made HTML what it is today. No, they weren&#39;t perfect, but it is mistakes that we learn from.&lt;/p&gt;
&lt;p&gt;These obsolete tags represent experiments in web development—some more successful than others. They&#39;re a reminder that the web platform we use today is the result of decades of trial, error, and evolution. And who knows? Maybe someday developers will look back at our current HTML practices with the same bemused affection.&lt;/p&gt;
&lt;p&gt;We often think of the web as forever backwards compatible and never breaking, but that plainly isn&#39;t the case. As we&#39;ve seen, there are plenty of elements that have been left behind in the march of progress. The web evolves, standards change, and what was once cutting-edge becomes a curious footnote in the platform&#39;s history.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Styling by Language: Using the lang Attribute for Multilingual Design</title>
    <link href="https://htmhell.dev/adventcalendar/2025/21/"/>
    <updated>2025-12-21T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/21/</id>
    <content type="html">by Julia Undeutsch&lt;br&gt;&lt;style&gt;
  @import url(&#39;https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&amp;family=Noto+Sans:ital,wght@0,100..900;1,100..900&amp;family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&amp;display=swap&#39;);

  :lang(en) {
  font-family: &quot;Nunito Sans&quot;, sans-serif;
  }

  :lang(ja) {
    font-family: &quot;Noto Sans JP&quot;, sans-serif;
  }

  p.adjust:lang(ja) {
    font-weight: 300;
  }

  span.adjust:lang(en) {
    font-weight: 400;
  }

  h2.adjust:lang(ja) {
    font-weight: 500;
    letter-spacing: 0.05em;
  }

  h2.adjust span:lang(en) {
    font-family: &quot;Noto Sans&quot;, sans-serif;
    font-size: 1.06em;
    letter-spacing: 0;
    vertical-align: -0.03em;
  }
&lt;/style&gt;
&lt;h2 id=&quot;when-east-meets-west-(on-the-same-page)&quot;&gt;When East Meets West (on the Same Page)&lt;/h2&gt;
&lt;p&gt;If you’ve ever built a bilingual English – Japanese website, you know the struggle. English uses letters with ascenders, descenders, and varying widths. Japanese, on the other hand, mixes three scripts: &lt;a href=&quot;https://en.wikipedia.org/wiki/Kanji&quot;&gt;kanji&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Hiragana&quot;&gt;hiragana&lt;/a&gt;, and &lt;a href=&quot;https://en.wikipedia.org/wiki/Katakana&quot;&gt;katakana&lt;/a&gt;, each forming balanced, square-like characters.&lt;/p&gt;
&lt;p&gt;Already last year, I told you about a special HTML element that you can use to style this scripts. Read my post &lt;a href=&quot;https://www.htmhell.dev/adventcalendar/2024/12/&quot;&gt;HTML and CSS I didn&#39;t even know about before I started creating content&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is not usually a big problem if the entire page is in one language. But when Latin letters are mixed with Japanese characters, as is increasingly the case, the font becomes more difficult to handle.&lt;/p&gt;
&lt;p&gt;That means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Japanese text usually needs more line height to breathe.&lt;/li&gt;
&lt;li&gt;Kanji often appear denser and more detailed than Latin letters.&lt;/li&gt;
&lt;li&gt;Western fonts can feel too “light” next to Japanese text.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where the &lt;code&gt;lang&lt;/code&gt; attribute becomes your best friend. And he brings a plus one: CSS.&lt;/p&gt;
&lt;h2 id=&quot;let-the-language-drive-the-design&quot;&gt;Let the Language Drive the Design&lt;/h2&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Welcome to Starbucks.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ja&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;スターバックスへようこそ。&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:lang(en)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nunito Sans&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:lang(ja)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Noto Sans JP&quot;&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p lang=&quot;en&quot;&gt;Welcome to Starbucks.&lt;/p&gt;
&lt;p lang=&quot;ja&quot;&gt;スターバックスへようこそ。&lt;/p&gt;
&lt;p&gt;Here, the English text uses &lt;strong&gt;Nunito&lt;/strong&gt;, which has friendly, rounded shapes. The Japanese version pairs quite good with &lt;strong&gt;Noto Sans JP (Google Fonts)&lt;/strong&gt;, which was designed specifically as a typeface for all writing systems around the world. Since the content is separate, both fonts appear suitable and visually balanced.&lt;br /&gt;
Read more about the &lt;a href=&quot;https://fonts.google.com/noto/specimen/Noto+Sans+JP&quot;&gt;Noto: A typeface for the world&lt;/a&gt; project.&lt;/p&gt;
&lt;h2 id=&quot;font-weight-and-visual-balance&quot;&gt;Font Weight and Visual Balance&lt;/h2&gt;
&lt;p&gt;However, when both writing systems are mixed together, which is common in the Japanese language today, typographical mismatches become noticeable. Meaning, When mixing languages, a font weight of &lt;code&gt;400&lt;/code&gt; for Japanese might look visually heavier than &lt;code&gt;400&lt;/code&gt; in Latin text because kana systems are more complex in shape.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ja&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Starbucks&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;へようこそ。&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p lang=&quot;ja&quot;&gt;&lt;span lang=&quot;en&quot;&gt;Starbucks&lt;/span&gt;へようこそ。&lt;/p&gt;
&lt;p&gt;You can correct this by slightly adjusting weights between languages:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:lang(en)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 400&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:lang(ja)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 300&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p lang=&quot;ja&quot; class=&quot;adjust&quot;&gt;&lt;span lang=&quot;en&quot; class=&quot;adjust&quot;&gt;Starbucks&lt;/span&gt;へようこそ。&lt;/p&gt;
&lt;p&gt;This subtle change keeps both scripts visually balanced without the Japanese text looking darker. But if you look more closely and highlight the text, you will notice that the default line height of the whole text is slightly different, due to the different fonts used. And the whole thing becomes even more challenging when kanji characters are mixed in with the text.&lt;/p&gt;
&lt;h2 id=&quot;kanji-density-and-design&quot;&gt;Kanji: Density and Design&lt;/h2&gt;
&lt;p&gt;Kanji are logographic characters—each one carries meaning, not just sound. Because they’re compact but information-dense, large blocks of kanji can look heavier.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Apple unveils the new iPhone 17 Pro.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ja&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Apple&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;が新型&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;iPhone 17 Pro&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;を発表。&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 lang=&quot;en&quot;&gt;Apple unveils the new iPhone 17 Pro.
&lt;h2 lang=&quot;ja&quot;&gt;
  &lt;span lang=&quot;en&quot;&gt;Apple&lt;/span&gt;が新型&lt;span lang=&quot;en&quot;&gt;iPhone 17 Pro&lt;/span&gt;を発表。
&lt;/h2&gt;
&lt;p&gt;You can help readability with&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generous &lt;code&gt;line-height&lt;/code&gt; (1.7–1.9)&lt;/li&gt;
&lt;li&gt;slightly looser letter spacing (&lt;code&gt;letter-spacing: 0.05em&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;a not too heavy &lt;code&gt;font-weight&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;avoiding &lt;code&gt;all-caps&lt;/code&gt; Latin text near kanji — caps feel bulky by comparison&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:lang(ja)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Noto Sans JP&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 500&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;letter-spacing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.05em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;:lang(en)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Noto Sans&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1.06em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* +5% larger than Japanese */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;letter-spacing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;vertical-align&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -0.03em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* align baseline slightly */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 lang=&quot;ja&quot; class=&quot;adjust&quot;&gt;&lt;span lang=&quot;en&quot;&gt;Apple&lt;/span&gt;が新型&lt;span lang=&quot;en&quot;&gt;iPhone 17 Pro&lt;/span&gt;を発表。&lt;/h2&gt;
&lt;p&gt;When styled this way, the English and Japanese text sit naturally on the same line — adjusting the English spans with a slightly larger font size and a small &lt;code&gt;vertical-align&lt;/code&gt; nudge raises their baseline just enough to match the Japanese characters. The result feels balanced in both weight and rhythm — one cohesive headline, not two scripts stitched together.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;Bonus Tip: Variable Fonts!&lt;/strong&gt; Google’s &lt;a href=&quot;https://fonts.google.com/knowledge/glossary/variable_fonts&quot;&gt;Variable Fonts&lt;/a&gt; make it even easier to fine-tune weight and width dynamically between scripts. If you use &lt;code&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings&quot;&gt;font-variation-settings&lt;/a&gt;&lt;/code&gt;, you can ensure text looks balanced across both languages at every viewport size.&lt;/p&gt;
&lt;h2 id=&quot;takeaway&quot;&gt;Takeaway&lt;/h2&gt;
&lt;p&gt;Multilingual design isn’t just about translation — it’s about typographic empathy. English and Japanese each have their own rhythm, density, and shape language. Using the &lt;code&gt;lang&lt;/code&gt; attribute with the right fonts helps you respect both, creating an experience that feels natural to all readers.&lt;/p&gt;
&lt;p&gt;Next time you use different scripts on your page, don’t just think about switching words. Think about switching &lt;em&gt;style&lt;/em&gt;, and let your typography speak both languages fluently.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fonts.google.com/noto&quot;&gt;Noto: A typeface for the world&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fonts.google.com/knowledge/glossary/variable_fonts&quot;&gt;Variable Fonts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h2&gt;</content>
  </entry>
  
  
    
  
  <entry>
    <title>The many lives of the page title</title>
    <link href="https://htmhell.dev/adventcalendar/2025/20/"/>
    <updated>2025-12-20T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/20/</id>
    <content type="html">by Katrin Kampfrath&lt;br&gt;&lt;p&gt;The page title — together with its co-star, the favicon — appears on stage in the browser tab. It shows up in search results. It’s announced by screen readers when a page loads. And it even becomes the default name when you bookmark a page.&lt;/p&gt;
&lt;p&gt;It lives in the &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; tag within in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of the document, supposedly unseen and often overlooked. Most tips and tricks around the page title focus on SEO benefits. But that’s not all: it also plays a vital role in the user flow of navigating the web.&lt;/p&gt;
&lt;h2 id=&quot;the-user-experience-of-a-page-title&quot;&gt;The user experience of a page title&lt;/h2&gt;
&lt;p&gt;Clicking a link and having a new page load is the defining usage pattern of the world wide web. How do we know we clicked the right link? How do we know to which tab to return to when we switched to another program?&lt;/p&gt;
&lt;p&gt;For screen reader users the page title is among the first things announced. On page load, sighted users will most likely first notice the H1 heading. When coming from another application or browser tab, the page title helps us identify the right window or browser tab. A page title identifies or describes a page and as such reassures us that we are indeed on the chosen page.&lt;/p&gt;
&lt;h2 id=&quot;the-page-title-in-complex-user-flows&quot;&gt;The page title in complex user flows&lt;/h2&gt;
&lt;p&gt;One overlooked aspect of the page title is its use in more complex user flows, for example a multi-step form split across several screens.&lt;/p&gt;
&lt;p&gt;I specifically use the term &amp;quot;screen&amp;quot; here — multi-step user flows are often built with JavaScript as multiple screens on one route (effectively, under one URL). From a developer&#39;s perspective, it is just one page. From a user&#39;s perspective, however, these are multiple pages.&lt;/p&gt;
&lt;p&gt;Let&#39;s consider a few multi-step user flows with potential page titles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;multi-step form&lt;/strong&gt; is a very common user flow, such as a checkout process or an application form. A typical page title for all screens is &amp;quot;Checkout - site name&amp;quot;. A more contextual title would be &amp;quot;Payment details - Checkout - site name&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Search results&lt;/strong&gt; that are placed across several pages. A typical page title for all screens is &amp;quot;Search results - site name&amp;quot;. A more contextual title would be &amp;quot;17 search results for {search term} - site name&amp;quot;.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;online learning platform&lt;/strong&gt; where each chapter consists of the learning content and related exercises. A typical page title for all screens is &amp;quot;{Name of chapter} - site name&amp;quot;. A more precise title would be &amp;quot;Page 1 - {Name of chapter} - site name&amp;quot;, &amp;quot;Exercise 1 - {Name of chapter} - site name&amp;quot;, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profile pages&lt;/strong&gt; with several settings tabs for appearance, notifications, activity and so on. A typical page title for all screens is &amp;quot;Profile - site name&amp;quot;. A more precise title for each screen would be &amp;quot;Appearance - Profile – site name&amp;quot;, &amp;quot;Notifications – Profile – site name&amp;quot;, and so on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In all examples, users benefit from a unique page title per screen, describing the specific content of what is currently displayed on the page.&lt;/p&gt;
&lt;h3 id=&quot;example-a-multi-step-form&quot;&gt;Example: A multi-step form&lt;/h3&gt;
&lt;p&gt;Let us dive deeper with the example of a multi-step form. Say we&#39;re buying a bike insurance. First, we enter our name and address. Then the bike details, such as purchase price, serial number, and whether it&#39;s an e-bike. Then payment details. The design is one screen per block of information, with no other main content.&lt;/p&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/20/bike-insurance.png&quot; width=&quot;740&quot; height=&quot;569&quot; loading=&quot;lazy&quot; alt=&quot;Browser tab for entering the bike details mentioned in the previous paragraph. In the center there are the form fields, on the left side is a navigation for the multiple steps, the browser tab shows the page title &#39;Buy bike insurance step 2&#39;.&quot; /&gt;
&lt;p&gt;The user navigates through the form. They enter their name and address, click “Next,” and move on to the bike details. Then they realise they don’t remember the exact purchase price. They open their email app to check — and while they&#39;re there, another email catches their eye. They click a link, open another tab, and get distracted.&lt;/p&gt;
&lt;p&gt;Returning to the insurance form should be as seamless as possible. Users likely scan all browser tabs first to find the right one. Clear page titles make it easy to identify where they left off.&lt;/p&gt;
&lt;p&gt;Consider these two possible titles:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;quot;Buy bike insurance - Company Name&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;Bike details - Step 2 of 4 · Buy bike insurance - Company Name&amp;quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first one identifies the form, but doesn’t reinforce the user&#39;s progress. The second one stells the user exactly where they are in the process.&lt;/p&gt;
&lt;h2 id=&quot;relevant-wcag-requirements&quot;&gt;Relevant WCAG requirements&lt;/h2&gt;
&lt;p&gt;So far, we’ve looked at this from a user-experience point of view. Next, we look at what is needed from an accessibility compliance perspective.&lt;/p&gt;
&lt;p&gt;In the Web Content Accessibility Guidelines (WCAG) there are two success criteria related to our topic:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/WCAG22/#page-titled&quot;&gt;Success Criterion 2.4.2 Page Titled&lt;/a&gt; checks whether a page title describes the topic or purpose of the current page.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/WCAG22/#link-purpose-in-context&quot;&gt;Success Criterion 2.4.4 Link Purpose (In Context)&lt;/a&gt; concerns the links on a page.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With regard to accessibility and legal requirements, the WCAG (also included in the European standard EN 301549) states minimum requirements. Think of text-to-background color contrast: the ratio of 4.5:1 is the minimum, but stronger contrast is always better.&lt;/p&gt;
&lt;p&gt;Going back to our bike insurance example, this is how we would audit this process at our company.&lt;/p&gt;
&lt;p&gt;For Success Criterion 2.4.2 Page Titled we check:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Does each step have a unique URL?&lt;/strong&gt; Then the page title needs to mention the specific topic of the current page in the page title, such as &amp;quot;Bike details&amp;quot; or &amp;quot;Bike details step 2 of 4&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If there are no unique URLs&lt;/strong&gt; (i.e. the form always starts at step 1), the overall form process must be sufficiently reflected in the page title. &amp;quot;Buy bike insurance - company name&amp;quot; would pass the success criterion. In an audit, we would then add a recommendation to include the current step for user-experience reasons.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For Success Criterion 2.4.4 Link Purpose (In Context), things are a little less clear. The main intent of the success criterion is that &amp;quot;&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Understanding/link-purpose-in-context.html&quot;&gt;users understand what each link will do&lt;/a&gt;.&amp;quot; The criterion focuses on the &amp;quot;read a link&amp;quot; part, so an accessibility audit will check the link texts on a given page to see if all links on one page are distinguishable from each other. This aspect is the minimum requirement.&lt;/p&gt;
&lt;p&gt;Nonetheless, the user flow still plays a role. Recall the typical flow: read a link, click a link, have a new page load. In the WCAG understanding document for this criterion, it says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Having the link and the title agree, or be very similar, is good practice and provides continuity between the link &#39;clicked on&#39; and the web page that the user lands on.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Adding context about the current step in a flow or the current page in a set of pages helps all users stay oriented.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Give your page sufficiently unique page titles. What is sufficient depends on the implementation and design details of your website.&lt;/p&gt;
&lt;p&gt;Keep the user flow in mind. The page title is a key element to reassure users they are indeed on the page they intended to be.&lt;/p&gt;
&lt;p&gt;Developer experience is not the same as user experience. As developers we know how things work on a technical level, and we might easily forget how users perceive a website. Never assume people will visit your site only in one straightforward session with no distractions. Clear, contextual titles help people stay oriented when they return.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/WCAG22/&quot;&gt;Web Content Accessibility Guidelines (WCAG) 2.2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Document/title&quot;&gt;MDN – Document.title property&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://accessibility-cookbook.com/&quot;&gt;Manuel Matuzović – Web Accessibility Cookbook&lt;/a&gt;, chapter &amp;quot;1.2 Describe the Document&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.smashingmagazine.com/printed-books/inclusive-front-end-design-patterns/&quot;&gt;Heydon Pickering – Inclusive Design Patterns&lt;/a&gt;, chapter &amp;quot;The &amp;lt;title&amp;gt; Element&amp;quot;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hidde.blog/accessible-page-titles-in-a-single-page-app/&quot;&gt;Hidde de Vries – &amp;quot;Accessible page titles in a Single Page App&amp;quot;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dequeuniversity.com/checklists/web/page-title&quot;&gt;Deque University – Page Title Checklist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Semantics beyond the tag name</title>
    <link href="https://htmhell.dev/adventcalendar/2025/19/"/>
    <updated>2025-12-19T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/19/</id>
    <content type="html">by Nathan Knowler&lt;br&gt;&lt;p&gt;There is a terrible epidemic that plagues the web: &lt;i&gt;divitis&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;If you’re unfamiliar, &lt;dfn&gt;&lt;i&gt;divitis&lt;/i&gt;&lt;/dfn&gt; is a condition where a website uses an unholy amount of &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements. Some of the worst cases even include &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s used as buttons—&lt;em&gt;blasphemy!&lt;/em&gt;&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;site-header&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;site-title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;divs r us&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;navigation&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;link&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;my favourite divs&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;link&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;moor divs&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;main&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;container&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;container-inner&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;card&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;card-inner&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;card-header&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;              &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;i love div&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;all my friends are divs&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;card-footer&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;              &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;button&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;accept div as your lord and saviour&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;site-footer&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;div-webring&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;button&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;join the divitis webring&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;button next&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;next&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;button prev&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;previous&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To avoid &lt;i&gt;divitis&lt;/i&gt;, authors are often encouraged to use &lt;i&gt;semantic HTML&lt;/i&gt;. As it turns out, HTML has over a hundred elements that are not named &lt;code&gt;div&lt;/code&gt; or &lt;code&gt;span&lt;/code&gt;. Semantic HTML elements describe what their content is.&lt;/p&gt;
&lt;p&gt;Inspired by this newfound responsibility, authors open the lexicon of HTML elements and begin to compose… &lt;em&gt;absolute gibberish.&lt;/em&gt;&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;my-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;divs suck&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;and so do classes&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;who needs classes when you have semantic HTML. combine elements however you’d like to explore new possibilities.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;nav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/hell&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;I have no class&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;nav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;my-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;my-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;replace all your divs with sections&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;they’re so semantic&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;whenever I don’t know what element to choose, section is there for me. section is my best friend forever.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;nav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/hell&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;become semantic with sections&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;nav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;my-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, this might not seem like gibberish on the surface—it might actually seem like it makes a lot of sense. The problems will become more apparent throughout this post. We cannot simply use HTML elements based on their tag names and expect them to translate to anything actually meaningful.&lt;/p&gt;
&lt;p&gt;To be fair, this is to be expected of anyone learning a new language. However, a problem on the web is that authors delude themselves into thinking that they are “writing semantic HTML,” therefore gaining all of the benefits that are understood to come with that like accessibility, and they never advance past that stage.&lt;/p&gt;
&lt;p&gt;It’s like when my own child confidently declares, after learning a handful of words in Japanese, “I know Japanese.” It’s cute and I’m not going to argue with it, because they’re a child.&lt;/p&gt;
&lt;p&gt;You’re likely not a child though, so I will tell it to you straight: &lt;em&gt;this is not cute.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once you’ve recovered from that devastating realization, we can proceed.&lt;/p&gt;
&lt;p&gt;To actually write semantic HTML, we need to know what elements mean beyond just what we infer from their tag names and how to use them. So, how do we find that out?&lt;/p&gt;
&lt;h2 id=&quot;where-html-semantics-come-from&quot;&gt;Where HTML semantics come from&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://html.spec.whatwg.org/multipage/&quot;&gt;The HTML standard&lt;/a&gt; is what defines HTML elements. For example, we can find the definition of the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element in &lt;a href=&quot;https://html.spec.whatwg.org/multipage/grouping-content.html#the-main-element&quot;&gt;section 4.4.14&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;main&lt;/code&gt; element represents the dominant contents of the document.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Beyond the definition, the standard also includes rules and guidance for usage:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A document must not have more than one &lt;code&gt;main&lt;/code&gt; element that does not have the &lt;code&gt;hidden&lt;/code&gt; attribute specified.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;A &lt;dfn&gt;hierarchically correct &lt;code&gt;main&lt;/code&gt; element&lt;/dfn&gt; is one whose ancestor elements are limited to &lt;code&gt;html&lt;/code&gt;, &lt;code&gt;body&lt;/code&gt;, &lt;code&gt;div&lt;/code&gt;, &lt;code&gt;form&lt;/code&gt; without an accessible name, and autonomous custom elements. Each &lt;code&gt;main&lt;/code&gt; element must be a hierarchically correct &lt;code&gt;main&lt;/code&gt; element.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From these descriptions, we can gather that using the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element for the main content of a card component, which can be used multiple times like the ones in the earlier “gibberish” example, would be incorrect:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;my-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- … --&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- first card main content --&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- … --&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;my-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;my-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- … --&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- second card main content --&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- … --&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;my-card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tag names are not enough for us to understand what an element is for. We need to adopt HTML’s own definitions for semantic elements.&lt;/p&gt;
&lt;h3 id=&quot;why-follow-the-html-standard?&quot;&gt;Why follow the HTML Standard?&lt;/h3&gt;
&lt;p&gt;I’m not your god, and neither is the HTML Standard—but if you choose to use HTML elements for how you perceive them, things break in ways you can’t control. Assistive tech, legal requirements, user expectations... it all hinges on the platform’s actual definitions. Ignore them and, well, your documents might just end up &lt;a href=&quot;https://www.htmhell.dev/&quot;&gt;in hell&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;but-what-about-aria?-cant-i-just-use-that-instead?&quot;&gt;But what about ARIA? Can’t I just use that instead?&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://w3c.github.io/aria/&quot;&gt;Accessible Rich Internet Applications&lt;/a&gt;, more commonly known by the acronym ARIA, is a set of roles and attributes that can be used in HTML to add accessibility related semantics to web content.&lt;/p&gt;
&lt;p&gt;It can be tempting to think that we don’t need semantic HTML, instead we can just sprinkle our &lt;i&gt;divitis&lt;/i&gt; with &lt;em&gt;holy&lt;/em&gt; ARIA roles and attributes. Well, while this can improve the accessibility of that hoard of elements, we’re likely breaking &lt;a href=&quot;https://www.w3.org/TR/using-aria/#firstrule&quot;&gt;the first rule of ARIA usage&lt;/a&gt;: don’t use ARIA if you don’t need to.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;accept div as your lord and saviour&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Many semantic HTML elements have what’s called &lt;i&gt;implicit ARIA semantics&lt;/i&gt;. These are ARIA roles and properties that the browser has mapped for us. Instead of needing to explicitly write out the ARIA semantics for an element each time you use it, we can use semantic HTML elements as a shorthand for these.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This machine kills fascists&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Beyond simply being a shorthand for a set of ARIA semantics, built-in HTML elements also include the necessary functionality and presentation that would be expected of an element bearing such semantics. In many cases, this means that you don’t need to write any JavaScript for your HTML to work as expected. Using JavaScript in lieu of built-in HTML functionality is wasteful and error prone, degrading the usability of your website.&lt;/p&gt;
&lt;p&gt;Now that we understand the folly of ignoring the first rule of ARIA usage, let’s turn our attention to &lt;i&gt;implicit ARIA semantics&lt;/i&gt; and how they work in semantic HTML.&lt;/p&gt;
&lt;h2 id=&quot;the-implicit-aria-semantics-of-html&quot;&gt;The implicit ARIA semantics of HTML&lt;/h2&gt;
&lt;p&gt;Along with the definitions for each element, the HTML standard includes accessibility considerations for both authors (i.e. you and I) and implementors (i.e. the people implementing the elements in browsers). The linked document for authors is called &lt;a href=&quot;https://w3c.github.io/html-aria/&quot;&gt;“ARIA in HTML”&lt;/a&gt; and the one for implementors is called &lt;a href=&quot;https://w3c.github.io/html-aam/&quot;&gt;“HTML Accessibility API Mappings” (HTML-AAM)&lt;/a&gt;. The each of these links will jump to the relevant bits for the element in question.&lt;/p&gt;
&lt;p&gt;Both of these include what the implicit ARIA semantics are for HTML elements and attributes. “ARIA in HTML” is more geared towards authors: it includes both rules and recommendations for ARIA attribute usage with HTML. HTML-AAM includes specifics of how elements should be mapped to various accessibility APIs including, but not limited to, ARIA.&lt;/p&gt;
&lt;p&gt;Turning again to the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element, we can see that &lt;a href=&quot;https://w3c.github.io/html-aria/#el-main&quot;&gt;it has an implicit ARIA role of &lt;code&gt;main&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If we look at heading elements like &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;, we see that &lt;a href=&quot;https://w3c.github.io/html-aria/#el-h1-h6&quot;&gt;they have an implicit ARIA role of &lt;code&gt;heading&lt;/code&gt; along with an implicit &lt;code&gt;aria-level&lt;/code&gt; of whatever number is a part of the tag name&lt;/a&gt; (i.e. HTML only includes six heading levels).&lt;/p&gt;
&lt;p&gt;Beyond element tag names, there are three details I want to point out in these documents:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Both an element’s attributes and its context can effect its implicit ARIA semantics.&lt;/li&gt;
&lt;li&gt;Some elements do not have implied semantics unless they are named.&lt;/li&gt;
&lt;li&gt;Not all elements have significant implicit ARIA semantics. That’s not to say they never will, but this gives us a good idea of where we can prioritize our time.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let’s dig into some examples.&lt;/p&gt;
&lt;h3 id=&quot;attributes-affect-implicit-semantics&quot;&gt;Attributes affect implicit semantics&lt;/h3&gt;
&lt;p&gt;Consider the following elements:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Anchor&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;https://example.com&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Anchor with an &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;code&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;href&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;code&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; attribute&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Are these both links?&lt;/p&gt;
&lt;p&gt;No, they aren’t. The first is just an anchor element. It’s implicit ARIA role is &lt;code&gt;generic&lt;/code&gt; which is not interesting for accessibility APIs. CSS also doesn’t even consider it a link as it will not match the &lt;code&gt;:any-link&lt;/code&gt; or &lt;code&gt;:link&lt;/code&gt; pseudo-class selectors.&lt;/p&gt;
&lt;p&gt;Since the latter anchor element has an &lt;code&gt;href&lt;/code&gt; attribute, it is considered a link, and therefore has the implicit ARIA role of &lt;code&gt;link&lt;/code&gt; and can be matched by the above mentioned semantic pseudo-class selectors with CSS.&lt;/p&gt;
&lt;h3 id=&quot;naming-affects-implicit-semantics&quot;&gt;Naming affects implicit semantics&lt;/h3&gt;
&lt;p&gt;A popular favourite among those first starting out with semantic HTML is the &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; element. What is often never realized is that it has no valuable ARIA semantics if it is not named (i.e. its implicit role is &lt;code&gt;generic&lt;/code&gt;). This makes it not much different than using a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; (i.e. its implicit role is also &lt;code&gt;generic&lt;/code&gt;).&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Insignificant section&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;section-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;section-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Significant document region&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that said, please do not go name &lt;em&gt;all&lt;/em&gt; of your &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; elements!&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;section-1-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;section-1-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Top one hundred reason I love sections&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;…&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;section-2-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;section-2-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Section is whatever I want it to be&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;…&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;section-3-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;section-3-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Section is my friend&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;…&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A labelled &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; element will have &lt;a href=&quot;https://w3c.github.io/aria/#region&quot;&gt;the &lt;code&gt;region&lt;/code&gt; ARIA role&lt;/a&gt;. This is what’s called a &lt;dfn&gt;&lt;i&gt;landmark&lt;/i&gt;&lt;/dfn&gt;. &lt;a href=&quot;https://tetralogical.com/blog/2022/03/18/landmarks/&quot;&gt;Landmarks&lt;/a&gt; are important sections of a document that a user might benefit from easy access to.&lt;/p&gt;
&lt;p&gt;The problem here is that everything is a landmark, then nothing is a landmark.&lt;/p&gt;
&lt;p&gt;It can be easy to think that labelling your &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; elements satisfies the requirement for using them, but that is not the case here. Both the meaning of the tag name and the HTML definition of a &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; element is way more generic than the &lt;code&gt;region&lt;/code&gt; ARIA role. Before you label your &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;  elements ensure they make sense as regions, otherwise, you’ll likely be making it more difficult to find what’s important on a page. If you’re already using &lt;a href=&quot;https://tetralogical.com/blog/2022/02/28/headings/&quot;&gt;a good heading structure&lt;/a&gt; throughout your document, that is good enough for what you’re likely trying to do.&lt;/p&gt;
&lt;h3 id=&quot;context-affects-implicit-semantics&quot;&gt;Context affects implicit semantics&lt;/h3&gt;
&lt;p&gt;HTML elements can have different implicit ARIA semantics when used in different contexts.&lt;/p&gt;
&lt;p&gt;For example, the &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt; elements have an important meaning for documents when used outside of the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element or any other sectioning content element.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Header content&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Main content of the document&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Footer content&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this scenario, the &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; element’s implicit ARIA role is &lt;code&gt;banner&lt;/code&gt; and the &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt; element’s implicit ARIA role is &lt;code&gt;contentinfo&lt;/code&gt;. Documents should only have one of each of these landmarks.&lt;/p&gt;
&lt;p&gt;That does not mean that you cannot use either of these elements in other places within your document. When we review &lt;a href=&quot;https://html.spec.whatwg.org/multipage/sections.html#the-header-element&quot;&gt;the definition of a &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; element&lt;/a&gt; it says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The &lt;code&gt;header&lt;/code&gt; element represents a group of introductory or navigational aids.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That implies much broader usage than &lt;a href=&quot;https://w3c.github.io/aria/#banner&quot;&gt;the definition of the &lt;code&gt;banner&lt;/code&gt; role&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“A &lt;code&gt;landmark&lt;/code&gt; that contains mostly site-oriented content, rather than page-specific content.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Until 2025, when used inside of the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element or &lt;a href=&quot;https://html.spec.whatwg.org/multipage/dom.html#sectioning-content&quot;&gt;sectioning content&lt;/a&gt;, &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt; elements were mapped with a &lt;code&gt;generic&lt;/code&gt; role which means they didn’t have any value for accessibility purposes. After relatively recent changes to the latest ARIA spec and HTML-AAM drafts, in these contexts they have been mapped to new ARIA roles: &lt;a href=&quot;https://w3c.github.io/aria/#sectionheader&quot;&gt;&lt;code&gt;sectionheader&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://w3c.github.io/aria/#sectionfooter&quot;&gt;&lt;code&gt;sectionfooter&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;banner landmark role&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;sectionheader role&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Article content&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;sectionfooter role&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;contentinfo landmark role&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;footer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As of writing, these changes have been implemented in Chromium-based browsers and Safari. &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1893684&quot;&gt;Firefox has yet to implement them&lt;/a&gt;. With that said, as these roles are new, the support from assistive technologies will likely be non-existent or quite limited.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt; elements are examples of context being an important factor for implicit ARIA semantics. At first, only specific usage was used for setting the landmark roles. Now, later on, the broader usage allowed of these elements in other contexts can be exposed semantically.&lt;/p&gt;
&lt;h3 id=&quot;a-combinations-of-these-factors-affect-implicit-semantics&quot;&gt;A combinations of these factors affect implicit semantics&lt;/h3&gt;
&lt;p&gt;Sometimes an element’s implicit semantics are informed by a combination of the factors that we’ve explored so far. Consider the &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;p&gt;In the following situations, the &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt; element’s implicit role is &lt;code&gt;complementary&lt;/code&gt; (a landmark) because it’s scoped to the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element or the &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; element:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Main content.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Complementary to the main content, but standalone.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Main content&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Complementary to the main content, but standalone.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you mark up your blog posts with an &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; element which is sectioning content, then unnamed &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt; elements have the &lt;code&gt;generic&lt;/code&gt; role.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Some article&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Some content, blah, blah, blah…&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Failed attempted at complementary.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only way to make this element have the &lt;code&gt;complementary&lt;/code&gt; role is to use &lt;code&gt;aria-labelledby&lt;/code&gt; or &lt;code&gt;aria-label&lt;/code&gt;. That could be a challenge if the content has no heading. You may need to be creative about wrapping part of the content to use as a label or introduce a visually hidden label if you want to avoid some of &lt;a href=&quot;https://adrianroselli.com/2019/11/aria-label-does-not-translate.html&quot;&gt;the translation pitfalls of &lt;code&gt;aria-label&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Some article&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Some content, blah, blah, blah…&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;aside&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;complementary-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;complementary-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Failed attempt&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; at complementary.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;aside&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All of this is not something someone could have inferred from the HTML standard alone. This is why documents like &lt;a href=&quot;https://w3c.github.io/html-aria/&quot;&gt;“ARIA in HTML”&lt;/a&gt; and &lt;a href=&quot;https://w3c.github.io/html-aam/&quot;&gt;HTML-AAM&lt;/a&gt; are invaluable for good semantic usage.&lt;/p&gt;
&lt;h3 id=&quot;custom-elements-can-have-implicit-semantics-too&quot;&gt;Custom elements can have implicit semantics too&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://html.spec.whatwg.org/multipage/custom-elements.html&quot;&gt;Custom elements&lt;/a&gt; are an HTML feature that allow authors to define their own HTML elements. A tag name can be defined as a custom element using the &lt;code&gt;window.customElements.define()&lt;/code&gt; method in JavaScript. Like built-in HTML elements, custom elements can have their own implicit ARIA semantics. This is set using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals&quot;&gt;&lt;code&gt;ElementsInternals&lt;/code&gt;&lt;/a&gt; API.&lt;/p&gt;
&lt;p&gt;Here is an example of defining a custom element and setting an implicit ARIA role for it:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HellButtonElement&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTMLElement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; internals &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attachInternals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      internals&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;role &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;button&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;// Continue implementing button functionality 🙈&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  customElements&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;not-a-div&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; HellButtonElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;not-a-div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;A div is not a button&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;not-a-div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you create custom elements, you become responsible for communicating their purpose to other authors. This should also include any implicit semantics you’ve set, as well as, what you consider good authoring practice to be when using them.&lt;/p&gt;
&lt;p&gt;I highly recommend using HTML itself as a model for how you build custom elements. In many ways, that might mean thinking less like an author and more like an implementor or a specification writer. “How do I create elements for others to use?” Implicit semantics are an important part of that because they allow you to &lt;a href=&quot;https://www.w3.org/TR/design-principles/#priority-of-constituencies&quot;&gt;put other authors first&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;test-test-test&quot;&gt;Test, test, test&lt;/h2&gt;
&lt;p&gt;In the same way that you can spend a whole lot of time writing valid, semantic HTML that has no implicit ARIA semantics, you can also spend a whole lot of time on writing HTML according to the specifications that actually isn’t implemented in any browser or that is implemented incorrectly in browsers. This is why testing is vital.&lt;/p&gt;
&lt;p&gt;Testing might look like checking what ARIA roles and properties are computed for elements in a browser’s developer tools (&lt;a href=&quot;https://devtoolstips.org/tips/en/see-accessibility-tree/&quot;&gt;use the accessibility tree in Chrome/Edge and Firefox&lt;/a&gt; or &lt;a href=&quot;https://webkit.org/web-inspector/elements-tab/#node-panel&quot;&gt;Accessibility section of the Node Panel in Safari’s Web Inspector&lt;/a&gt;). It also might look like actually using assistive technologies such as screen readers or voice control. It is very helpful to understand how assistive technology users experience various elements and so seeking real feedback is invaluable to the testing process. Just make sure to show anyone you do involve that you value their time and labour.&lt;/p&gt;
&lt;p&gt;Testing helps us understand what is valuable and what we should focus on. I can spend a whole lot of time trying to perfectly mark up all of my words using &lt;a href=&quot;https://html.spec.whatwg.org/multipage/text-level-semantics.html#text-level-semantics&quot;&gt;text-level semantics&lt;/a&gt;, but then realize through testing that I’ve delivered little to no semantic value to assistive technology users.&lt;/p&gt;
&lt;p&gt;Courses such as &lt;a href=&quot;https://practical-accessibility.today/&quot;&gt;Sara Soueidan’s Practical Accessibility&lt;/a&gt; or &lt;a href=&quot;https://testingaccessibility.com/&quot;&gt;Marcy Sutton’s Testing Accessibility&lt;/a&gt; are great resources for those wanting to get started with testing various assistive technologies.&lt;/p&gt;
&lt;h2 id=&quot;go-forth-and-actually-write-semantic-html&quot;&gt;Go forth and actually write semantic HTML&lt;/h2&gt;
&lt;p&gt;We’ve learned that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;HTML tag names are not a reliable way of understanding what an element is for.&lt;/li&gt;
&lt;li&gt;The HTML standard defines what semantic HTML elements are for.&lt;/li&gt;
&lt;li&gt;Some semantic HTML elements also have implicit ARIA semantics, and in some cases that depends on what attributes are set, if the element has an accessible name, the context the element is used in, and even a combination of these things.&lt;/li&gt;
&lt;li&gt;Custom elements can have implicit ARIA semantics too.&lt;/li&gt;
&lt;li&gt;Don’t take anyone’s word for it: test it yourself.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://html.spec.whatwg.org/multipage/&quot;&gt;The HTML Standard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://w3c.github.io/aria/&quot;&gt;Accessible Rich Internet Applications (WAI-ARIA)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://w3c.github.io/html-aria/&quot;&gt;ARIA in HTML&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://w3c.github.io/html-aam/&quot;&gt;HTML Accessibility API Mappings (HTML-AAM)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tetralogical.github.io/screen-reader-HTML-support/lookup/lookup.html&quot;&gt;Screen Reader HTML Support – Lookup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tetralogical.com/blog/2021/09/29/browsing-with-a-desktop-screen-reader/&quot;&gt;Tetralogical’s “Browsing with a desktop screen reader”&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;The first in a series about browsing with various kinds of assistive technologies (linked within).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/people-use-web/&quot;&gt;How People with Disabilities Use the Web&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Forms are a badly designed part of HTML</title>
    <link href="https://htmhell.dev/adventcalendar/2025/18/"/>
    <updated>2025-12-18T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/18/</id>
    <content type="html">by Jens Grochtdreis&lt;br&gt;&lt;p&gt;Forms were likely one of the reasons why browser vendors joined forces in the WHATWG in 2004. They felt that HTML standardization was heading into the wrong direction and wanted more practical relevance. While this may be an oversimplification, if true, it highlights the failure of the WHATWG (i.e., the browser vendors) and, subsequently, the W3C. Although the newly standardized form elements and features all point into the right direction, they are incomplete and unfinished. The fact that this is still the case, even more than ten years after HTML5 became a recommendation, is alarming. I will concentrate in this article on forms and especially on missing elements, inconsistent behaviour and the problems with styling.&lt;/p&gt;
&lt;h2 id=&quot;new-form-elements&quot;&gt;New Form Elements&lt;/h2&gt;
&lt;p&gt;The WHATWG introduced several new form elements and attributes into the HTML specification, e.g. the email input, telephone input, date field, and range slider. Most of these are simply new types of the input element. This approach was clever — a great example of progressive enhancement. If a browser hasn’t implemented a particular input type yet, a plain text field serves as a fallback. Developers can then use JavaScript if needed. However, when the new elements are supported, JavaScript becomes unnecessary.&lt;/p&gt;
&lt;p&gt;This progressive-enhancement model works well for simple inputs. So these new elements are intentionally very simple – essentially shortcuts for single-value fields. They combine regular expressions for validation, an ARIA role, and sometimes trigger a specialized virtual keyboard on mobile phones and tablets. They are similar to web components based on the input element, but are integrated directly into the browser, so no JavaScript is needed for the element to appear. And because they are standardized, the code is consistent across implementations.&lt;/p&gt;
&lt;p&gt;Combinations of different form elements have unfortunately not been considered at all. As examples, I would like to mention the &lt;a href=&quot;https://open-ui.org/components/combobox.explainer/&quot;&gt;combobox&lt;/a&gt; and the &lt;a href=&quot;https://open-ui.org/components/enhanced-range-input.explainer/&quot;&gt;range slider&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-combobox&quot;&gt;The Combobox&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://component.gallery/components/combobox/&quot;&gt;combobox&lt;/a&gt; is a combination of a select and a search field. Fluent UI provides a &lt;a href=&quot;https://fluentsite.z22.web.core.windows.net/0.66.2/maximize/dropdown-example-search-multiple-shorthand/false&quot;&gt;combobox component&lt;/a&gt;, as does &lt;a href=&quot;https://ant.design/~demos/select-demo-multiple&quot;&gt;Ant Design&lt;/a&gt;. In both cases, only the search field is a form field. The select is simulated by a list in Fluent, while Ant Design uses a div. The selected options are displayed as (fake) buttons using span and svg elements. This has little to do with actual forms.&lt;/p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/18/combobox-github.png&quot; alt=&quot;A button has opend ea layer which is in essence a combination of an input-field with search-icon and a select element.&quot; loading=&quot;lazy&quot; width=&quot;306&quot; height=&quot;372&quot; /&gt;
  &lt;figcaption&gt;The combobox (called select-panel) from the &lt;a href=&quot;https://primer.style/product/components/select-panel/&quot;&gt;Github-design system&lt;/a&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
  &lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/18/combobox-ant-design.png&quot; alt=&quot;Combobox showing a select with two marked entries. These entries are as well represented as clickable tags inside a formfield where you could type for new tags/entries.&quot; loading=&quot;lazy&quot; width=&quot;407&quot; height=&quot;385&quot; /&gt;
  &lt;figcaption&gt;The combobox from the design-system of &lt;a href=&quot;https://ant.design/~demos/select-demo-multiple&quot;&gt;ant-design&lt;/a&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;the-enhanced-range-element&quot;&gt;The Enhanced Range Element&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/range&quot;&gt;range element&lt;/a&gt; can unfortunately only represent a single value. The frequently needed &lt;a href=&quot;https://open-ui.org/components/slider.research/&quot;&gt;range slider&lt;/a&gt; for two or more values (e.g. for shopping portals) does not exist. You&#39;ll have to build it yourself. The well-known &lt;a href=&quot;https://refreshless.com/nouislider/&quot;&gt;noUiSlider&lt;/a&gt; simulates the slider for one or more values consistently with a div. At least ARIA attributes are used throughout. The same goes with the version by &lt;a href=&quot;https://quasar.dev/vue-components/range/&quot;&gt;Quasar&lt;/a&gt;. No form elements were harmed. It’s a pity that this obvious use case was not standardized.&lt;/p&gt;
&lt;h2 id=&quot;built-in-validation&quot;&gt;Built-in Validation&lt;/h2&gt;
&lt;p&gt;Standardizing validation in the browser was a smart idea. There are built-in regex rules for validation, which can be manually overridden. Validation is controlled via attributes and a standardized JavaScript API, which is great. In practice, however, you quickly run into details that aren’t flexibly solved. This leads to custom solutions using JavaScript.&lt;/p&gt;
&lt;p&gt;There is no simple, built-in way to collect all error messages and display them at the top or bottom of the form without JavaScript. Nor is there a way to communicate the total number of errors to the user. Error messages at the element itself are shown via a popup, which cannot be styled or repositioned. For any improvements in usability and clearer communication, you&#39;ll need JavaScript. While this is done through a unified API, it still isn’t possible with plain HTML.&lt;/p&gt;
&lt;p&gt;HTML needs better built-in options for handling errors. We should be able to control this with attributes, not JavaScript. The less JavaScript is needed, the faster the page will be.&lt;/p&gt;
&lt;h2 id=&quot;inconsistent-browser-support&quot;&gt;Inconsistent browser support&lt;/h2&gt;
&lt;p&gt;Form elements don&#39;t have standardized, consistent capabilities or appearance. I don&#39;t know whether browser vendors weren&#39;t willing to align on this or simply didn&#39;t see the need. Either way, consistent usability, features, and appearance would help both users and developers. For example, browsers hook into the operating system&#39;s built-in color picker, which seems sensible – but these pickers can’t be styled and differ in functionality. Android and iOS replace the HTML date picker with their own native widget, which is great on mobile. But on desktop, each browser presents a completely different UI, and none of it is customizable.&lt;/p&gt;
&lt;p&gt;The number input offers increment/decrement arrows in one browser but not in another. The usefulness of these arrows is debatable. The date field is only read aloud &lt;a href=&quot;https://tetralogical.github.io/screen-reader-HTML-support/lookup/lookup.html#input-date&quot;&gt;by the native screen reader on iOS&lt;/a&gt;) when a date is already present; it is not announced as a date field. The email input is announced as an email field &lt;a href=&quot;https://tetralogical.github.io/screen-reader-HTML-support/lookup/lookup.html#input-email&quot;&gt;only by Voice Over on MacOS&lt;/a&gt;. Other screen readers don&#39;t announce the semantics. If browser vendors are leading the standardization of these features, I expect better coordination and consistent implementation.&lt;/p&gt;
&lt;p&gt;Semantic information needs to be exposed to screen readers. Without that, the new input type feels only half-baked – basically just a text input with built-in validation and a tailored onscreen keyboard. And both of those could have been achieved without introducing a dedicated email input.&lt;/p&gt;
&lt;p&gt;Inconsistent behaviour and appearance may or may not irritate users. It mostly irritates developers, designers and their clients. Inconsistency is a nightmare if you want to provide a seamless and identical look and feel of your page/application through the differnet devices and browsers. It might as well irritate users if the form looks very different on a smartphone and a notebook.&lt;/p&gt;
&lt;h2 id=&quot;partially-miserable-styling-options&quot;&gt;Partially Miserable Styling Options&lt;/h2&gt;
&lt;p&gt;Styling form elements is a major challenge that often ends in failure. Developers frequently hide the native control and style the label instead – or hide the control entirely and replace it with a JavaScript-driven construction of divs or lists that can be freely styled.&lt;/p&gt;
&lt;p&gt;Fundamentally, styling form elements is miserable. This is why &lt;a href=&quot;https://2024.stateofhtml.com/en-US/features/forms/&quot;&gt;58% of participants&lt;/a&gt; in the &amp;quot;State of HTML 2024&amp;quot; survey identified styling as by far the biggest pain point with forms.&lt;/p&gt;
&lt;p&gt;Browser vendors are currently more active in CSS than in HTML, so there’s a faint glimmer of hope on the horizon. Chromium has introduced the customizable select, based on an &lt;a href=&quot;https://open-ui.org/components/customizableselect/&quot;&gt;Open UI proposal&lt;/a&gt;, and Brecht deRuyte has dedicated a &lt;a href=&quot;https://utilitybend.com/blog/the-customizable-select-part-one-history-trickery-and-styling-the-select-with-css&quot;&gt;series of articles&lt;/a&gt; on the new, fantastic possibilities.&lt;/p&gt;
&lt;p&gt;It’s a start, but the broader problem remains: all controls hidden inside the browser’s shadow DOM need consistent, standardized structure so they can be styled reliably. At CSSDay 2025, Tim Nguyen presented the Working Draft “&lt;a href=&quot;https://www.w3.org/TR/2025/WD-css-forms-1-20250325/&quot;&gt;CSS Form Control Styling Level 1&lt;/a&gt;” – early work, but promising. I hope it matures quickly and finds its way into browsers.&lt;/p&gt;
&lt;p&gt;Without meaningful progress here, we’ll be stuck with &lt;a href=&quot;https://open-ui.org/components/datepicker.research/&quot;&gt;JavaScript-based date pickers&lt;/a&gt; and other custom controls for the foreseeable future. What’s the point of having a native element if we have to replace it at the first opportunity because we can’t style it?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://wpt.fyi/interop-2025&quot;&gt;Interop 2025&lt;/a&gt; didn’t include any focus on form controls. Hopefully some proposals make it into Interop 2026 once the &lt;a href=&quot;https://github.com/web-platform-tests/interop/blob/main/2026/selection-process.md&quot;&gt;selection process&lt;/a&gt; concludes (hopefully by the time this article is published).&lt;/p&gt;
&lt;h2 id=&quot;lack-of-further-development&quot;&gt;Lack of Further Development&lt;/h2&gt;
&lt;p&gt;We are still missing important form elements, and developers have to simulate them with JavaScript. Standardizers could have addressed these gaps in recent years. They didn&#39;t. Could it be that they think that we already have all the &amp;quot;building blocks&amp;quot; needed – that developers can simply assemble new controls using JavaScript and Web Components?&lt;/p&gt;
&lt;p&gt;Taken to its logical extreme, this argument would reduce HTML to a handful of primitive elements. Everything else would be rebuilt as custom components, each with its own attributes, ARIA wiring, and implementation quirks. That can’t seriously be the goal.&lt;/p&gt;
&lt;p&gt;In my view, HTML elements are, in a sense, browser-specific web components, but with some crucial advantages: they do not require JavaScript, and they behave the same for all end users and devices. Non-standard controls, on the other hand, come in dozens of variations, built on different foundations, and with varying quality. Standardization exists precisely so we don’t all have to reinvent them.&lt;/p&gt;
&lt;h2 id=&quot;hope-is-rising&quot;&gt;Hope Is Rising&lt;/h2&gt;
&lt;p&gt;The lack of standardization leads to many different approaches to the same problem. What they have in common is that they have little or nothing to do with actual form elements.&lt;/p&gt;
&lt;p&gt;Fortunately, practitioners have come together in the &amp;quot;&lt;a href=&quot;https://open-ui.org/&quot;&gt;Open UI&lt;/a&gt;&amp;quot; community group to advance the standardization of HTML and CSS. They describe several features that are missing as standards in HTML. For the combobox, Open UI has created &lt;a href=&quot;https://open-ui.org/components/combobox.explainer/&quot;&gt;a proposal&lt;/a&gt;. I hope it will be implemented in browsers and standardized soon.&lt;/p&gt;
&lt;p&gt;The same applies to the range slider with more than one value. Open UI also offers a great idea for a long-overdue &lt;a href=&quot;https://open-ui.org/components/enhanced-range-input.explainer/&quot;&gt;extension of the standard&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-new-wave-of-innovation-is-needed&quot;&gt;A New Wave of Innovation Is Needed&lt;/h2&gt;
&lt;p&gt;This article is a very rough overview of the state of forms. My main demands for innovation are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We need more complex form fields as standard elements, such as a combobox.&lt;/li&gt;
&lt;li&gt;We need a range input with multiple handles.&lt;/li&gt;
&lt;li&gt;We need much better styling opportunities for every form element. The new stylable select shows the right direction.&lt;/li&gt;
&lt;li&gt;Form validation should be controlled by HTML-attributes instead of JavaScript. It&#39;s styling should be easy and consistent between browsers.&lt;/li&gt;
&lt;li&gt;Screenreaders should communicate form semantic without flaws.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The innovation of forms should be part of a much larger initiative. WHATWG and W3C demonstrated at the beginning of the millennium that this is possible. After two decades, it is time to revive this spirit and take HTML to a new level. We’ve seen hints of this recently – elements like &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;, the popover API, and renewed work on customizable form controls show that the platform can still evolve in meaningful ways. But these feel like isolated wins rather than part of a broader push.&lt;/p&gt;
&lt;p&gt;Modern websites no longer fit the document-centric model HTML was created for. A typical news homepage mixes headlines, images, teasers, and interactive elements in ways the original spec never anticipated. The New York Times even present teasers without headlines at all. This diversity shows how little shared foundation there is for developers today – and why HTML needs a broader, more coordinated evolution beyond isolated improvements.&lt;/p&gt;
&lt;p&gt;Modern Websites and especially Webapps need a new paradigm. They evolved far beyond the inventor&#39;s idea and it won&#39;t stop evolving. The W3C should respond with new elements and paradigms. The document analogy should stand alongside interactive applications as equals. The more that is standardized in this regard, the better it is for the industry. And end users will also benefit from consistently high-quality websites.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Don&#39;t leave the screen reader hungry</title>
    <link href="https://htmhell.dev/adventcalendar/2025/17/"/>
    <updated>2025-12-17T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/17/</id>
    <content type="html">by Geri Reid&lt;br&gt;&lt;p&gt;Screen readers don’t always announce what’s visually on screen. This article explores that gap - through the medium of burritos.&lt;/p&gt;
&lt;h2 id=&quot;the-burrito-you-cant-order&quot;&gt;The burrito you can&#39;t order&lt;/h2&gt;
&lt;p&gt;A customer complained they couldn&#39;t order a burrito. &amp;quot;The menu advertises burritos, but my screen reader won&#39;t let me order one!&amp;quot;&lt;/p&gt;
&lt;p&gt;I was baffled. The menu was about as Mexican as a Yorkshire pudding. There was no mention of a burrito.&lt;/p&gt;
&lt;p&gt;After a lot of searching, I discovered someone had dropped an emoji into the heading:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Sandwiches 🌯&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Visually, it looked decorative and &lt;em&gt;kind of like a sandwich&lt;/em&gt;. But screen readers don&#39;t read an emoji as decoration, they announce its &lt;a href=&quot;https://unicode.org/emoji/charts/full-emoji-list.html&quot;&gt;Unicode character name&lt;/a&gt;. So screen reader users heard: &amp;quot;Sandwiches, Burrito.&amp;quot;&lt;/p&gt;
&lt;p&gt;That little emoji isn&#39;t just sitting in your markup looking pretty. It&#39;s making promises your website can&#39;t keep. One tiny flourish in your heading tag and suddenly your sandwich bar sounds like a taqueria.&lt;/p&gt;
&lt;h2 id=&quot;whats-on-the-menu?&quot;&gt;What&#39;s on the menu?&lt;/h2&gt;
&lt;p&gt;What I&#39;m highlighting here is screen readers don&#39;t consistently announce what you see visually on the screen. This article explores the gap between what HTML gives you for free and what you need to supply yourself.&lt;/p&gt;
&lt;p&gt;I&#39;ve made some quick reference tables to demonstrate how popular screen readers JAWS, NVDA, and VoiceOver handle elements, showing where HTML does the work and where you need to add stuff in addition.&lt;/p&gt;
&lt;p&gt;Documenting and recording screen reader requirements is also problematic, so it sometimes falls through the gaps between design and code. I’ve got some ideas to help solve this.&lt;/p&gt;
&lt;h3 id=&quot;you-hungry?&quot;&gt;You hungry?&lt;/h3&gt;
&lt;p&gt;Since you&#39;re probably craving Mexican food by now, we&#39;re going to frame this through the medium of burritos. Put your apron on, taquero - it&#39;s time to get cooking!&lt;/p&gt;
&lt;p&gt;Let’s imagine the browser is your tortilla: it holds everything together. HTML adds some fillings by default. For a successful burrito, you need the right toppings. The trick is knowing which toppings to add and when to stop.&lt;/p&gt;
&lt;h2 id=&quot;what-you-get-for-free-(the-fillings)&quot;&gt;What you get for free (the fillings)&lt;/h2&gt;
&lt;p&gt;Like a burrito that comes with rice, beans and your choice of protein, semantic HTML automatically packs the essentials into your tortilla. Correctly marked-up headings, links, buttons, lists, form controls, and tables are announced by default. And like a burrito starts with a good tortilla, screen readers work best when paired with their preferred browser:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JAWS with Chrome on Windows&lt;/li&gt;
&lt;li&gt;NVDA with Firefox or Chrome on Windows&lt;/li&gt;
&lt;li&gt;VoiceOver with Safari on Apple&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&#39;s how JAWS, NVDA and VoiceOver screen readers announce for me using their default settings (I&#39;ve included my testing specs in the footer). Use this as a guide. Your announcements might differ slightly based on verbosity and device settings, browser and software version. The way you navigate also changes what you hear. For example, using a heading shortcut key may produce a different announcement than letting the screen reader read through linearly.&lt;/p&gt;
&lt;p&gt;The exact announcement doesn&#39;t really matter.&lt;/p&gt;
&lt;p&gt;What matters is knowing what you get for free and when you have to add something to get meaningful announcements.&lt;/p&gt;
&lt;div class=&quot;u-oa&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Exemplary announcements&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;JAWS says&lt;/th&gt;
&lt;th&gt;NVDA says&lt;/th&gt;
&lt;th&gt;Mac OS VoiceOver says&lt;/th&gt;
&lt;th&gt;Annotation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Burritos&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“Burritos, Heading level 1”&lt;/td&gt;
&lt;td&gt;“Burritos, Heading level 1”&lt;/td&gt;
&lt;td&gt;“Heading level 1, Burritos”&lt;/td&gt;
&lt;td&gt;No extras needed. Use correct heading levels for structure.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;button&amp;gt;Checkout&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“Checkout button”&lt;/td&gt;
&lt;td&gt;“Checkout, button”&lt;/td&gt;
&lt;td&gt;“Checkout, button”&lt;/td&gt;
&lt;td&gt;No extras needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;a href=&amp;quot;burrito.html&amp;quot;&amp;gt;Order burrito&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“Order burrito, link”&lt;/td&gt;
&lt;td&gt;“Order burrito, link”&lt;/td&gt;
&lt;td&gt;“link, Order burrito”&lt;/td&gt;
&lt;td&gt;No extras needed. Just make sure the link text makes sense out of context.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;ul&amp;gt; &amp;lt;li&amp;gt;Burrito&amp;lt;/li&amp;gt; &amp;lt;li&amp;gt;Taco&amp;lt;/li&amp;gt; &amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“List of 2 items. Bullet Burrito. Bullet Taco. List end”&lt;/td&gt;
&lt;td&gt;“List with 2 items. Bullet Burrito. Bullet Taco. Out of list”&lt;/td&gt;
&lt;td&gt;“List 2 items.
Bullet Burrito, 1 of 2. 
Bullet Taco, 2 of 2.
End of list.”&lt;/td&gt;
&lt;td&gt;No extra needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;label for=name&amp;quot;&amp;gt;Name&amp;lt;/label&amp;gt; &amp;lt;input id=&amp;quot;name&amp;quot; type=&amp;quot;text&amp;quot;&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“Name, edit”&lt;/td&gt;
&lt;td&gt;“Name, edit”&lt;/td&gt;
&lt;td&gt;“Name, edit text”&lt;/td&gt;
&lt;td&gt;No extra needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;input id=&amp;quot;cheese&amp;quot; type=&amp;quot;checkbox&amp;quot;&amp;gt; &amp;lt;label for=&amp;quot;cheese&amp;quot;&amp;gt;Extra cheese&amp;lt;/label&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“Extra cheese, check box, not checked”&lt;/td&gt;
&lt;td&gt;“Check box, not checked, Extra cheese”&lt;/td&gt;
&lt;td&gt;“Extra cheese, unticked, tick box”&lt;/td&gt;
&lt;td&gt;No extra needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;button disabled&amp;gt;Not taking orders&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“Order, button, unavailable”&lt;/td&gt;
&lt;td&gt;“Button unavailable, Order”&lt;/td&gt;
&lt;td&gt;“Order, dimmed, button”&lt;/td&gt;
&lt;td&gt;No extra needed. Visually appears disabled, not focusable.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 id=&quot;what-you-must-supply-(the-toppings)&quot;&gt;What you must supply (the toppings)&lt;/h2&gt;
&lt;p&gt;Here’s where you roll up your sleeves. These elements stay silent or may not announce as you’d expect until you add the right toppings.&lt;/p&gt;
&lt;div class=&quot;u-oa&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Exemplary announcements with missings attributes&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;JAWS says&lt;/th&gt;
&lt;th&gt;NVDA says&lt;/th&gt;
&lt;th&gt;Mac OS VoiceOver says&lt;/th&gt;
&lt;th&gt;Annotation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;img src=&amp;quot;burrito.png&amp;quot;&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;quot;Unlabelled graphic&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Unlabelled graphic&amp;quot;&lt;/td&gt;
&lt;td&gt;“Unlabelled image” or &amp;quot;burrito.png&amp;quot;&lt;/td&gt;
&lt;td&gt;Add alt text describing the image. Or use &lt;code&gt;alt=&amp;quot;&amp;quot;&lt;/code&gt; if decorative.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;button&amp;gt;&amp;lt;svg&amp;gt;burrito svg icon&amp;lt;/svg&amp;gt;&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“unlabelled button”&lt;/td&gt;
&lt;td&gt;“button”&lt;/td&gt;
&lt;td&gt;“button”&lt;/td&gt;
&lt;td&gt;Add accessible name via &lt;code&gt;aria-label&lt;/code&gt; or &lt;code&gt;aria-labelledby&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;iframe src=&amp;quot;#&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;“frame”, or “frame 2 of 4” if multiple&lt;/td&gt;
&lt;td&gt;“frame”, or “frame 2 of 4” if multiple&lt;/td&gt;
&lt;td&gt;“frame”&lt;/td&gt;
&lt;td&gt;Add a descriptive &lt;code&gt;title&lt;/code&gt; for context.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The trick: add the toppings that matter, but don&#39;t overload the burrito. An overstuffed burrito can fall into your lap, potentially ruining a first date.&lt;/p&gt;
&lt;h2 id=&quot;edge-cases-and-oddities-(htmhells-kitchen)&quot;&gt;Edge cases and oddities (HTMHell&#39;s Kitchen)&lt;/h2&gt;
&lt;p&gt;These ingredients look tasty but behave unpredictably under heat. Use with caution or your markup might fall apart.&lt;/p&gt;
&lt;div class=&quot;u-oa&quot; tabindex=&quot;0&quot; role=&quot;region&quot; aria-label=&quot;Exemplary oddities&quot;&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;JAWS says&lt;/th&gt;
&lt;th&gt;NVDA says&lt;/th&gt;
&lt;th&gt;Mac OS VoiceOver says&lt;/th&gt;
&lt;th&gt;Annotation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;strong&amp;gt;Burrito!&amp;lt;/strong&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;quot;Burrito&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Burrito&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Burrito&amp;quot;&lt;/td&gt;
&lt;td&gt;Emphasis not reliably spoken on default verbosity settings. Don&#39;t rely on for meaning.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;em&amp;gt;Spicy&amp;lt;/em&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;quot;Spicy&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Spicy&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Spicy&amp;quot;&lt;/td&gt;
&lt;td&gt;Emphasis not reliably spoken on default verbosity settings. Don&#39;t rely on for meaning.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;£8 &amp;lt;s&amp;gt;£10&amp;lt;/s&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;quot;£8 strikethough deletion £10&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;£8 deleted £10&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;£8 £10&amp;quot; or &amp;quot;£8 deletion £10&amp;quot;&lt;/td&gt;
&lt;td&gt;Strikeout not reliably announced.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt; / &amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;quot;2, 2&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;2, 2&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;2, 2&amp;quot;&lt;/td&gt;
&lt;td&gt;Not read as superscript or subscript.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;hr&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;quot;separator&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;separator&amp;quot;&lt;/td&gt;
&lt;td&gt;Silent&lt;/td&gt;
&lt;td&gt;Don&#39;t rely on for meaning. Add &lt;code&gt;aria-label&lt;/code&gt; if the separation needs context.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;abbr title=&amp;quot;Street Provisions In Corn-based Envelopes&amp;quot;&amp;gt;SPICE&amp;lt;/abbr&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;quot;SPICE, Street Provisions In Corn-based Envelopes&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Spice&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Spice&amp;quot;&lt;/td&gt;
&lt;td&gt;Full title not reliably announced. Spell out abbreviation in text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🌯&lt;/td&gt;
&lt;td&gt;&amp;quot;Burrito&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Burrito&amp;quot;&lt;/td&gt;
&lt;td&gt;&amp;quot;Burrito&amp;quot;&lt;/td&gt;
&lt;td&gt;Emojis announce their &lt;a href=&quot;https://unicode.org/emoji/charts/full-emoji-list.html&quot;&gt;Unicode name&lt;/a&gt;. For decorative use, add &lt;code&gt;aria-hidden&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 id=&quot;help!-my-burrito-is-busted!&quot;&gt;Help! My burrito is busted!&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If you&#39;re second-guessing what should announce, TetraLogical recently released a &lt;a href=&quot;https://github.com/TetraLogical/screen-reader-HTML-support?tab=readme-ov-file&quot;&gt;detailed guide to screen reader announcements&lt;/a&gt; along with an &lt;a href=&quot;https://stevefaulkner.github.io/AT-browser-tests/&quot;&gt;HTML Element test file&lt;/a&gt;  you can run your screen reader over to test elements in isolation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you’re looking for video examples of how elements and components announce, check out the &lt;a href=&quot;https://www.atomica11y.com/accessible-web/&quot;&gt;HTML section of atomica11y&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you work on a Mac and need to test on Windows screen readers, try &lt;a href=&quot;https://assistivlabs.com/&quot;&gt;AssistivLabs&lt;/a&gt; or set up an &lt;a href=&quot;https://getutm.app/&quot;&gt;emulator like UTM&lt;/a&gt;. You can run NVDA for free and JAWS has a free 40 minute developer mode which is sufficient for testing. &lt;a href=&quot;https://webaim.org/projects/screenreadersurvey10/#primary&quot;&gt;40% of the screen reader market uses JAWS&lt;/a&gt; so if you only test on VoiceOver you might miss issues.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;documenting-screen-reader-requirements&quot;&gt;Documenting screen reader requirements&lt;/h2&gt;
&lt;p&gt;If you&#39;re building a website, you need a consistent way to document screen reader announcements. Don&#39;t leave it up to chance. Current design tools don&#39;t have space for accessibility information and much of it is non-visual, so it easily gets overlooked during implementation.&lt;/p&gt;
&lt;h3 id=&quot;documenting-with-design-annotation-kits&quot;&gt;Documenting with design annotation kits&lt;/h3&gt;
&lt;p&gt;Visual annotation kits for Figma, Sketch or Penpot offer a solution. There are plenty of excellent open-source examples shared in community files that you can tailor to your organisation&#39;s needs. If you&#39;re looking for inspiration, Jan Maarten and Daniel Henderson-Ede did a talk showcasing how &lt;a href=&quot;https://www.youtube.com/live/O1GmngpGokU?si=Y6uxWmX1Z6pxfRDD&quot;&gt;different design teams annotate for accessibility&lt;/a&gt; at this year&#39;s Inclusive Design 24.&lt;/p&gt;
&lt;p&gt;As a designer, I find it helpful to pair with an engineer and mark up design files together to capture all the accessibility requirements.&lt;/p&gt;
&lt;p&gt;A problem with sticky note annotations is that they often die in design files once development begins. Developers don&#39;t revisit design files, designers move on and the accessibility details you&#39;ve spent time documenting get lost. Even if they are used effectively in implementation, you end up rewriting a similar set of notes for subsequent projects.&lt;/p&gt;
&lt;h3 id=&quot;documenting-with-text&quot;&gt;Documenting with text&lt;/h3&gt;
&lt;p&gt;Text-based documentation in machine-readable formats (YAML, JSON, markdown tables, or structured specifications) solves this. Instead of static notes trapped in design files, if you record your annotations as text you can create queryable records that travel. Think of it like your restaurant having a digital ordering system instead of handwritten tickets. The kitchen gets the exact burrito order every time, with all the special instructions intact.&lt;/p&gt;
&lt;p&gt;These formats also unlock AI integration through tools like RAG or MCP servers. When a developer asks an AI assistant about a component, it can surface the exact accessibility requirements. You could even structure these specs to generate automated test criteria.&lt;/p&gt;
&lt;p&gt;The long game: shift to living documentation that can be queried on demand. Some clever folks like Nathan Curtis have already started ​to explore ways to &lt;a href=&quot;https://medium.com/@nathanacurtis/components-as-data-2be178777f21&quot;&gt;record specs with data&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;lets-wrap-up!-🌯&quot;&gt;Let&#39;s wrap up! 🌯&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;HTML gives you a tortilla full of free fillings: headings, lists, buttons, form controls, tables. However, some elements require you to add a topping to make them meaningful.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Document which toppings are needed so they don&#39;t get lost between design and development. Without clear documentation, developers have to guess at the requirements or skip them entirely, leaving accessibility as an afterthought rather than an integral part of the build.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember that a good burrito, like good markup, is about knowing which toppings to add and when to stop. Get it right and your screen reader users get a memorable burrito. Get it wrong and they&#39;re left with a stain on their shirt.&lt;/p&gt;
&lt;h3 id=&quot;about-geri-reid&quot;&gt;About Geri Reid&lt;/h3&gt;
&lt;p&gt;Geri is an accessibility and design systems nerd from London. As design and accessibility lead on design systems at News UK and Lloyds Banking Group, she helped some of the UK’s largest media and banking brands to design at scale. She is currently Lead Accessibility Specialist at Just Eat Takeaway.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blog: &lt;a href=&quot;https://gerireid.com/&quot;&gt;gerireid.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bluesky: &lt;a href=&quot;https://bsky.app/profile/gerireid.com&quot;&gt;@gerireid.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LinkedIn: &lt;a href=&quot;https://www.linkedin.com/in/gerireid/&quot;&gt;@gerireid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Screen reader testing on:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;JAWS (2025) with Chrome Version 140.0.7339.128 (Official Build) (64-bit) on Windows 11&lt;/li&gt;
&lt;li&gt;NVDA (2025) with Chrome Version 140.0.7339.128 (Official Build) (64-bit) on Windows 11&lt;/li&gt;
&lt;li&gt;VoiceOver (2025) with Safari Version 26.0.1 on Mac, Sequoia 15.7.1&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Giving pages a clear shape by using headings</title>
    <link href="https://htmhell.dev/adventcalendar/2025/16/"/>
    <updated>2025-12-16T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/16/</id>
    <content type="html">by Steve Barnett&lt;br&gt;&lt;p&gt;We can make our pages easier to understand by using headings to give our pages a clear shape. Our users might visually scan the page, use an extension or bookmarklet to list the headings, navigate using assistive technology like a screen reader, or ask AI for a summary of the page. High quality headings can make things better for everyone.&lt;/p&gt;
&lt;p&gt;In my day job as a Digital Accessibility Consultant, there are a couple of ways that I&#39;ve seen things go a bit... wonky. Let&#39;s go through the three most common issues, and how to fix them.&lt;/p&gt;
&lt;h2 id=&quot;text-should-not-be-a-heading&quot;&gt;Text &lt;em&gt;should not&lt;/em&gt; be a heading&lt;/h2&gt;
&lt;p&gt;Ah, this one&#39;s a real classic! When we have some big and bold text, for Design Reasons, we sometimes take a bit of a shortcut and mark it up as a heading. Let&#39;s say an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;, because it seems about the right size, or that’s what it says in the design file. But here&#39;s the thing: this text doesn&#39;t introduce or describe the content that follows. It just &amp;quot;needs&amp;quot; to be big for the look of it.&lt;/p&gt;
&lt;p&gt;This is an issue because when things are marked up as headings that are not headings, it makes the page harder to understand. Users of assistive technology like screen readers hear things read as headings of section that are not headings.&lt;/p&gt;
&lt;h3 id=&quot;an-example&quot;&gt;An example&lt;/h3&gt;
&lt;p&gt;Let&#39;s say we have a page explaining colours, RGB-style. We might have headings marked up as follows.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;Colours
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;Red&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;Green
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;Make it pop!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;Blue&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this case &amp;quot;Make it pop!&amp;quot; is just some big text, designed to be eye-catching. It&#39;s not the start of a section of content.&lt;/p&gt;
&lt;h3 id=&quot;how-to-fix-it&quot;&gt;How to fix it&lt;/h3&gt;
&lt;p&gt;Stop using HTML and start using CSS. Instead of using a heading element, using a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; or  &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element and use CSS to make it big and bold.&lt;/p&gt;
&lt;h2 id=&quot;text-should-be-a-heading&quot;&gt;Text &lt;em&gt;should&lt;/em&gt; be a heading&lt;/h2&gt;
&lt;p&gt;Now let&#39;s come from the other side. We look at a design and see some bold text. Some big, some bigger, some biggest. Sweet! We fling down a bunch of &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements, add some styles and we&#39;re done. It looks just like the design, chef&#39;s kiss, and so on. But here&#39;s the thing: this text looks like a heading, but doesn&#39;t have any semantics.&lt;/p&gt;
&lt;p&gt;This is an issue because when text is marked up as a heading even though it isn’t one, it makes the page harder to understand. People using bookmarklets or browser extensions to list headings won&#39;t see this text in the list of headings.&lt;/p&gt;
&lt;h3 id=&quot;an-example-2&quot;&gt;An example&lt;/h3&gt;
&lt;p&gt;Let&#39;s say we have a page explaining what the web is made of. We might have some big bold text marked up as follows.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;The world wide web
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;HTML&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;CSS&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;JavaScript&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this case &amp;quot;CSS&amp;quot; isn&#39;t just a paragraph. It&#39;s the start of a section of content.&lt;/p&gt;
&lt;h3 id=&quot;how-to-fix-it-2&quot;&gt;How to fix it&lt;/h3&gt;
&lt;p&gt;Stop using CSS and start using HTML. Instead of using a &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element, use a heading element at the right level to give it semantic structure: from &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt;. If we have some big and bold text that introduces or describes the content that follows, it should probably be a heading.&lt;/p&gt;
&lt;h2 id=&quot;headings-do-not-reflect-the-content-structure&quot;&gt;Headings do not reflect the content structure&lt;/h2&gt;
&lt;p&gt;Okay, we&#39;ve sorted out text that should and shouldn&#39;t be a heading: only things that are structural headings are marked as headings. Hooray! There&#39;s one more snag that we might hit: when the headings are in a weird order. For example: let&#39;s say we have a page listing edible things. We mark up &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;Fruit&lt;code&gt;&amp;lt;/h3&amp;gt;&lt;/code&gt; as a section, and then &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;Apples&lt;code&gt;&amp;lt;/h2&amp;gt;&lt;/code&gt; as a sub-section of Fruit. Maybe we&#39;ve done this because that&#39;s what the styles in the design file suggest. But here&#39;s the thing: it&#39;s wonky because the headings don&#39;t represent the hierarchical relationships.&lt;/p&gt;
&lt;p&gt;This is an issue because users of assistive technology like screen readers use headings to understand how each section of the page relates to each other and the page as a whole. When the headings are wonky, the shape of the page is harder to understand.&lt;/p&gt;
&lt;h3 id=&quot;how-to-fix-it-3&quot;&gt;How to fix it&lt;/h3&gt;
&lt;p&gt;Use HTML to give the headings the correct nesting and ordering. Use CSS to make them look appropriately sized and shiny.&lt;/p&gt;
&lt;p&gt;I like to start from the page as a whole and work my way down.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What’s the topic or purpose of this page? That text should be in an &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element near the top of the page.&lt;/li&gt;
&lt;li&gt;What are the sections of the page? The name of each section should be in an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; element, at the start of the section.&lt;/li&gt;
&lt;li&gt;What (if any) are the subsections of each section? The name of each subsection should be in an &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; element, at the start of the subsection.&lt;/li&gt;
&lt;li&gt;What (if any) are the sub-subsections of each subsection? The name of each sub-subsection should be in an &lt;code&gt;&amp;lt;h4&amp;gt;&lt;/code&gt; element, at the start of the sub-subsection.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And we keep going, down to an &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt; element. Although if you&#39;ve reached an &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt; element, it might be worth reviewing the content and seeing if there&#39;s Too Much Stuff there!&lt;/p&gt;
&lt;p&gt;The list of headings should read a bit like a table of contents for the page.&lt;/p&gt;
&lt;h2 id=&quot;other-weird-heading-things&quot;&gt;Other weird heading things&lt;/h2&gt;
&lt;p&gt;There are other aspects of wonkiness that may occur. Keep a watch for these too!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Heading text that doesn&#39;t describe the content that follows.&lt;/strong&gt; The words of the heading must introduce the section. Ask your friendly Content writer for help!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; shenanigans: no &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element, or multiple &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; elements.&lt;/strong&gt; Just one &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; element, please! It should describe the topic or purpose of page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skipped heading levels&lt;/strong&gt;, for example: jumping from an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; element to an &lt;code&gt;&amp;lt;h4&amp;gt;&lt;/code&gt; element, without an &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; between them. Keep the nesting and order correct: &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; elements for subsections of a section with an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; heading.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;accessibility-nerd-corner&quot;&gt;Accessibility nerd corner&lt;/h2&gt;
&lt;p&gt;The big three issues we started with all fall under &lt;a href=&quot;https://www.w3.org/TR/WCAG22/#info-and-relationships&quot;&gt;Web Content Accessibility Guidelines Success Criteria 1.3.1 Info and Relationships (A)&lt;/a&gt;: &amp;quot;Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.&amp;quot;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &amp;quot;Text should not be a heading&amp;quot; and &amp;quot;Text should be a heading&amp;quot; issues are about the information.&lt;/li&gt;
&lt;li&gt;The &amp;quot;Headings do not reflect the content structure&amp;quot; issue is about structure and relationships.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we spot these issue in the course of an &lt;a href=&quot;https://intopia.digital/services/accessibility-usability-testing/&quot;&gt;Accessibility Assessment&lt;/a&gt;, we usually log them as Medium Severity: it causes problems or frustrations for users.&lt;/p&gt;
&lt;p&gt;Headings that aren&#39;t descriptive fall under &lt;a href=&quot;https://www.w3.org/TR/WCAG22/#headings-and-labels&quot;&gt;WCAG Success Criteria 2.4.6 Headings and Labels (AA)&lt;/a&gt;. These are usually Medium Severity too.&lt;/p&gt;
&lt;h2 id=&quot;use-your-head(ings)&quot;&gt;Use your head(ings)&lt;/h2&gt;
&lt;p&gt;Using headings to give our pages a clear shape makes them easier to understand.&lt;/p&gt;
&lt;p&gt;Make sure that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;text that functions as a heading is marked up as a heading&lt;/li&gt;
&lt;li&gt;text that does not function as a heading is not marked up as a heading&lt;/li&gt;
&lt;li&gt;headings reflect the content structure&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;useful-tools&quot;&gt;Useful tools&lt;/h3&gt;
&lt;p&gt;Two of my favourite ways to visualise headings are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the Headings bookmarklet at &lt;a href=&quot;https://accessibility-bookmarklets.org/install.html&quot;&gt;Accessibility Bookmarklets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;the Headings toggle (in Ad hoc tools) of the &lt;a href=&quot;https://accessibilityinsights.io/docs/web/overview/&quot;&gt;Accessibility Insights for Web&lt;/a&gt; extension.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both of them add annotation-like boxes and text, making it easier scroll through and visually spot weird heading things.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Them’s the Breaks</title>
    <link href="https://htmhell.dev/adventcalendar/2025/15/"/>
    <updated>2025-12-15T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/15/</id>
    <content type="html">by Tyler Sticka&lt;br&gt;&lt;p&gt;On the web, it’s easy to take line breaks for granted.&lt;/p&gt;
&lt;p&gt;We get them for free between our headings, paragraphs, list items, &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements and more. We display them as-is in our code snippets thanks to &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;. And most magically of all, our browsers insert breaks &lt;em&gt;automatically&lt;/em&gt; where lines of text (or other text-like “inline” elements) would otherwise outgrow their container.&lt;/p&gt;
&lt;p&gt;But sometimes, that isn’t enough.&lt;/p&gt;
&lt;p&gt;Some words are too long and continuous to break automatically. Some words can be “orphaned” onto their own, lonely line. Occasionally, our content demands an overt break; more often, our designs call for their addition or removal.&lt;/p&gt;
&lt;p&gt;So it makes sense that HTML provides a few options for managing mid-content breaks. Some famously overused, others less known or understood:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The “break” element, &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The “word break opportunity” element, &lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The “soft hyphen” character, &lt;code&gt;&amp;amp;shy;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The “non-breaking space” character, &lt;code&gt;&amp;amp;nbsp;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s “break” down (&lt;a href=&quot;https://www.youtube.com/watch?v=AKtwlHV1-O8&quot;&gt;nyuk, nyuk&lt;/a&gt;) those techniques: What they do, when they’re appropriate, and alternatives to consider.&lt;/p&gt;
&lt;h2 id=&quot;the-&amp;quot;break&amp;quot;-element-lessbrgreater&quot;&gt;The “break” element, &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;99% of the time, line breaks in text that are truly &lt;em&gt;meaningful&lt;/em&gt; to your content will justify a new paragraph, list item, &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; or other block element.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; (“break”) element is for those rare exceptions.&lt;/p&gt;
&lt;p&gt;For example, a &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; can force a break between lines of poetry or song (apologies to &lt;a href=&quot;https://en.wikipedia.org/wiki/One_Step_Closer_(Linkin_Park_song)&quot;&gt;Linkin Park&lt;/a&gt;):&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Everything you say to me&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;br&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  (Takes me one step closer to the edge)&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;br&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  (And I’m about to break)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or within an address:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Breakside Brewery&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;br&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  1570 NW 22nd Ave.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;br&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Portland, Oregon 97210&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;address&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And… that’s pretty much it. As commonplace as &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; is, it’s rarely preferable to more semantic HTML.&lt;/p&gt;
&lt;h2 id=&quot;the-&amp;quot;word-break-opportunity&amp;quot;-element-lesswbrgreater&quot;&gt;The “word break opportunity” element, &lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt; element is &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;’s less famous, more introverted cousin. It inserts a break &lt;em&gt;only&lt;/em&gt; when the text will overflow and the browser can’t find a “break opportunity” (whitespace) of its own.&lt;/p&gt;
&lt;p&gt;You wouldn’t want to use &lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt; for most text: There’s no hyphenation or anything to indicate where breaks occur. But it can be useful when a string has predictable breakpoints that aren’t spaces.&lt;/p&gt;
&lt;p&gt;For example, the slashes in a URL or directory path:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;https://htmhell.dev&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;wbr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/adventcalendar&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;wbr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/2025&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;wbr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/17&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;wbr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;/index.html&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or dot notation in an object chain:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;namespace&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;wbr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.class&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;wbr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.object&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;wbr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.property&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt; should only be used to signify clear break points: You should &lt;em&gt;not&lt;/em&gt; attempt to auto-insert &lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt; elements willy-nilly as a form of general overflow avoidance. It is also a poor choice for any list-like content, such as breadcrumb navigation.&lt;/p&gt;
&lt;h2 id=&quot;the-&amp;quot;soft-hyphen&amp;quot;-character-andshy;&quot;&gt;The “soft hyphen” character, &lt;code&gt;&amp;amp;shy;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;&amp;amp;shy;&lt;/code&gt;(“soft hyphen”) character reference (&lt;code&gt;&amp;amp;#173;&lt;/code&gt; for the Unicode stans) functions a lot like &lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt;, except a hyphen is inserted just before the break:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;anti&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;shy;&quot;&gt;&amp;amp;shy;&lt;/span&gt;dis&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;shy;&quot;&gt;&amp;amp;shy;&lt;/span&gt;establishmen&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;shy;&quot;&gt;&amp;amp;shy;&lt;/span&gt;taria&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;shy;&quot;&gt;&amp;amp;shy;&lt;/span&gt;nism&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&amp;amp;shy;&lt;/code&gt; is also surprisingly configurable via CSS. You can replace the hyphens with a character of your choice:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;hyphenate-character&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;⋯&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or disable them entirely:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;hyphens&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The hyphenation makes &lt;code&gt;&amp;amp;shy;&lt;/code&gt; more suitable for typical prose than &lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt;. That said, hyphenation in general is a bit of a minefield:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It doesn’t work well in every language.&lt;/li&gt;
&lt;li&gt;Breaking up a word between two lines, hyphenated or not, can be challenging for many readers.&lt;/li&gt;
&lt;li&gt;While hyphenation has a long and rich typographic history, its readability has always been highly dependent on the size, layout and justification of the overall text. Dynamic content and responsive containers make it that much tougher to get right.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I occasionally find &lt;code&gt;&amp;amp;shy;&lt;/code&gt; helpful when I’m writing and notice a word flowing in a particularly troublesome way. I’d consider frequent usage a signal to simplify my verbiage or tweak my design.&lt;/p&gt;
&lt;h2 id=&quot;the-&amp;quot;non-breaking-space&amp;quot;-character-andnbsp;&quot;&gt;The “non-breaking space” character, &lt;code&gt;&amp;amp;nbsp;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Normally, whitespace characters are the most reliable indication of a line break opportunity. The &lt;code&gt;&amp;amp;nbsp;&lt;/code&gt; character openly &lt;em&gt;defies&lt;/em&gt; that convention, applying a space that is, much like &lt;a href=&quot;https://en.wikipedia.org/wiki/Unbreakable_Kimmy_Schmidt&quot;&gt;Kimmy Schmidt&lt;/a&gt;, &lt;em&gt;unbreakable&lt;/em&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;Keep&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;nbsp;&quot;&gt;&amp;amp;nbsp;&lt;/span&gt;it&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;nbsp;&quot;&gt;&amp;amp;nbsp;&lt;/span&gt;together&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(The non-breaking space is just one of &lt;a href=&quot;https://en.wikipedia.org/wiki/Whitespace_character#Unicode&quot;&gt;many whitespace characters&lt;/a&gt; that will prevent a string from breaking as you’d normally expect.)&lt;/p&gt;
&lt;p&gt;As useful as that sounds, &lt;code&gt;&amp;amp;nbsp;&lt;/code&gt; and its cousins should be considered a last resort. They don’t play very well with other techniques for managing breaking and text flow, and they’re virtually impossible to style without additional selectors or &lt;a href=&quot;https://css-tricks.com/modifying-specific-letters-with-css-and-javascript/&quot;&gt;truly epic hacks&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;gently-apply-your-breaks&quot;&gt;Gently Apply Your Breaks&lt;/h2&gt;
&lt;p&gt;If you’ve followed along to this point, you may notice a pattern: These techniques all have pretty limited use cases!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; for the rare break that’s actually part of the content (poems, addresses, etc.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;wbr&amp;gt;&lt;/code&gt; for weird run-on strings&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;shy;&lt;/code&gt; for very occasional hyphenation in prose&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;nbsp;&lt;/code&gt; when you must avoid a break at all cost&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For other mid-content break scenarios, your best bet is CSS!&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;display&lt;/code&gt;, we can stack inline elements as if they were blocks:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; grid&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Ms. Boop Squanklin,&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Beloved Activist &lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;amp;&quot;&gt;&amp;amp;amp;&lt;/span&gt; Icon&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or flow block elements together:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;hgroup&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; flex&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;flex-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; wrap&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;column-gap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1ch&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Heading&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Subtitle&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;hgroup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or keep key phrases wrapping as one:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  “Come Together” by&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; inline-block&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    The Beatles&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can encourage long strings to wrap more aggressively with &lt;code&gt;overflow-wrap&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;overflow-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; anywhere&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;/* or */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;overflow-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; break-word&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;/* or */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;word-break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; break-all&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rescue typographic orphans with &lt;code&gt;text-wrap&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;text-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; balance&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;/* or */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;text-wrap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pretty&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or micro-manage break behavior with &lt;code&gt;white-space&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.yolo-single-line&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;white-space&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; nowrap&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(We can even apply hyphenation and truncation via CSS, but these present their own challenges. See &lt;a href=&quot;https://cloudfour.com/thinks/justified-text-better-than-expected/&quot;&gt;my justified text explorations&lt;/a&gt; and &lt;a href=&quot;https://css-tricks.com/embracing-asymmetrical-design/&quot;&gt;some classic truncation wisdom from Karen McGrane&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;Content that calls for a semantic break is rare, but real: It’s good to understand your HTML options for that scenario. But once you’ve plopped in &lt;em&gt;one&lt;/em&gt; quick &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;, its immediacy makes it tempting to overuse.&lt;/p&gt;
&lt;p&gt;Resist the urge, write good markup, and embrace the accessibility, power and maintainability of CSS alternatives. Your audience and your project’s future maintainers will be happy you did!&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>The Wonderful World of Web Feeds</title>
    <link href="https://htmhell.dev/adventcalendar/2025/14/"/>
    <updated>2025-12-14T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/14/</id>
    <content type="html">by Maureen Holland&lt;br&gt;&lt;p&gt;Web feeds are incredible! And a bit confusing! Why are the feed links often called “RSS”? And why is this “RSS” feed in an &lt;code&gt;atom.xml&lt;/code&gt; file… hang on, what is &lt;code&gt;feed.json&lt;/code&gt; for? What are they even feeding into anyway?&lt;/p&gt;
&lt;p&gt;To start, web feeds are often referred to as “RSS” because RSS is the oldest format. &lt;a href=&quot;https://www.rssboard.org/rss-specification&quot;&gt;RSS&lt;/a&gt; stands for Really Simple Syndication. It is an XML-based specification for web content syndication (&lt;a href=&quot;https://help.apple.com/itc/podcasts_connect/#/itcb54353390&quot;&gt;including podcasts&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Syndication is the sale or licensing of material for publication or broadcasting by others. In &lt;a href=&quot;https://web.archive.org/web/20091009143514/http://www.museum.tv/archives/etv/S/htmlS/syndication/syndication.htm&quot;&gt;broadcast syndication&lt;/a&gt;, networks sell reruns of their original shows to other platforms, where those shows might reach a larger audience. In web content syndication, feeds package web content into a format that can “rerun” on a feed reader application. A key difference is that feeds are not sold to feed readers. The “audience” for web feeds has a much more active role to play. They are subscribers, choosing what content they want to follow and what reader they want to follow it on.&lt;/p&gt;
&lt;p&gt;Other web content syndication specifications include &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc4287&quot;&gt;Atom&lt;/a&gt; (also XML-based) and &lt;a href=&quot;https://www.jsonfeed.org/version/1.1/&quot;&gt;JSON&lt;/a&gt;. If you’re interested, &lt;a href=&quot;https://css-tricks.com/working-with-web-feeds-its-more-than-rss/#aa-rss-vs-atom-vs-json&quot;&gt;CSS Tricks has a breakdown of the technical distinctions between these formats&lt;/a&gt;. A web feed (even one that says it’s an “RSS” feed) could be any of these formats under the hood.&lt;/p&gt;
&lt;p&gt;A very basic web feed looks like this: &lt;a href=&quot;https://maureenholland.ca/magpie/feed.xml&quot;&gt;https://maureenholland.ca/magpie/feed.xml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Simplified example below:&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;rss&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;channel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;atom:&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://maureenholland.ca/magpie/feed.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Magpie&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;https://maureenholland.ca/magpie/&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		Blog of writer and web developer Maureen Holland. Untidy nest of shiny things.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;language&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;en-ca&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;language&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;A Vanilla Personal Site&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			https://maureenholland.ca/magpie/a-vanilla-personal-site&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;guid&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;isPermaLink&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			https://maureenholland.ca/magpie/a-vanilla-personal-site&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;guid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;pubDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Tue, 18 Apr 2023 12:00:00 GMT&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;pubDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			I rebuild my personal site every few years. This time, I decided I wanted to go as minimal as possible. It&#39;s been the most enjoyable iteration.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;			&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;description&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;channel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;rss&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This XML file includes general info about the feed (&lt;code&gt;channel&lt;/code&gt;) and lists one &lt;code&gt;item&lt;/code&gt; which contains a &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;link&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, publication date (&lt;code&gt;pubDate&lt;/code&gt;), and globally unique identifier (&lt;code&gt;guid&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;A feed reader, like &lt;a href=&quot;https://feedbin.com/home&quot;&gt;Feedbin&lt;/a&gt;, &lt;a href=&quot;https://netnewswire.com/&quot;&gt;NetNewsWire&lt;/a&gt;, or &lt;a href=&quot;https://www.newsblur.com/&quot;&gt;NewsBlur&lt;/a&gt;, is able to parse that information and serve it in a human-readable format that will look something like this:&lt;/p&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/14/simple-feed-in-reader.png&quot; width=&quot;1140&quot; height=&quot;372&quot; loading=&quot;lazy&quot; alt=&quot;Black text on white background. Title: A Vanilla Personal Site. Description: I rebuild my personal site every few years. This time, I decided I wanted to go as minimal as possible. It’s been the most enjoyable iteration. Gray text: maureenholland.ca, Apr 18 2023.&quot; /&gt;
&lt;p&gt;It uses the unique identifier to determine if an item in the feed is new. It can do this for any number of feeds, constantly updating a reading list of your favourite web content.&lt;/p&gt;
&lt;p&gt;Importantly, feed readers have no proprietary control over your feed list. If you are dissatisfied with your reader, you can export your feeds to an &lt;a href=&quot;https://opml.org/spec2.opml&quot;&gt;OPML&lt;/a&gt; (Outline Processor Markup Language) file and import them to a new reader later.&lt;/p&gt;
&lt;h2 id=&quot;the-joy-of-autodiscovery&quot;&gt;The Joy of Autodiscovery&lt;/h2&gt;
&lt;p&gt;Remember all that stuff about RSS and Atom and XML and JSON? Forget it!&lt;/p&gt;
&lt;p&gt;A subscriber shouldn’t have to know any of that technical detail. This is where &lt;a href=&quot;https://www.rssboard.org/rss-autodiscovery&quot;&gt;RSS Autodiscovery&lt;/a&gt; comes in.&lt;/p&gt;
&lt;p&gt;You can implement autodiscovery with a single line of HTML in the &lt;code&gt;head&lt;/code&gt; of your website (and if you’re using a blog platform, chances are it’s already there by default):&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Magpie&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://maureenholland.ca/magpie/feed.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, no one has to hunt for your site’s subscribe link (or “RSS” link or whatever). They can copy/paste the website address into their feed reader and let the application do the work of finding the feeds.&lt;/p&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/14/rss-autodiscovery.png&quot; width=&quot;1060&quot; height=&quot;442&quot; loading=&quot;lazy&quot; alt=&quot;A feed reader search input with the value: &#39;https://maureenholland.ca/magpie&#39;. The search correctly returns one rss.xml feed: Magpie, Blog of writer and web developer Maureen Holland.&quot; /&gt;
&lt;p&gt;If you want, you can also include separate links for different categories. &lt;a href=&quot;https://codex.wordpress.org/Customizing_Feeds&quot;&gt;WordPress&lt;/a&gt;, for example, automatically generates feeds for entries and comments. &lt;a href=&quot;https://ghost.org/integrations/custom-rss/&quot;&gt;Ghost&lt;/a&gt; includes a main post index, author archive, and tag archive.&lt;/p&gt;
&lt;p&gt;This is not required but can be helpful if your site has a lot of frequently updated content or a wide range of topics. Subscribers may prefer a subset of content (i.e. long form articles or short “Today I Learned” posts).&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Everything&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/feed.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Articles&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/articles.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;TIL&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/til.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;I started subscribing to web feeds after reading &lt;a href=&quot;https://timkadlec.com/remembers/2023-02-23-investing-in-rss/&quot;&gt;Tim Kadlec’s Investing in RSS&lt;/a&gt;. When I’m online, at some point, I will be checking my feed reader for a bit of inspiration. It’s a form of self-care to step out of the daily grind and step into someone else’s brain for a while. As much as I’ve learned from the articles I’ve read, it’s the feeling I’ve had reading them that I remember most, that spark of connection or revelation. If I’ve been offline for a while, the unread notifications can pile up, so I also consider it a form of self-care to select “Mark all as read.”&lt;/p&gt;
&lt;p&gt;If you’re already a fan of web feeds, check you’ve made it easy for others to find your feed with autodiscovery. If you’re new to web feeds, pick a reader and try it out for a month. Then switch to a different one, &lt;em&gt;just because you can&lt;/em&gt;.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;
This post owes a lot to Matt Webb’s great work on &lt;a href=&quot;https://aboutfeeds.com/&quot;&gt;https://aboutfeeds.com/&lt;/a&gt;.
&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Hell is other people&#39;s markup</title>
    <link href="https://htmhell.dev/adventcalendar/2025/13/"/>
    <updated>2025-12-13T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/13/</id>
    <content type="html">by Ian Lloyd (Lloydi)&lt;br&gt;&lt;p&gt;&lt;a href=&quot;https://www.htmhell.dev/&quot;&gt;HTMLHell&lt;/a&gt; started as a site that showed some of the finest, and by that I mean most &lt;strong&gt;awful&lt;/strong&gt;, examples of crimes against markup the world has to offer (and how these crimes can be put right). We’ve all seen some shit, man. But somewhere along the line, Manuel started &lt;a href=&quot;https://www.htmhell.dev/tips/&quot;&gt;HTML Heaven&lt;/a&gt;, covering decent markup and clever techniques. It&#39;s a good mix of dark and light, yin and yang. And what I wanted to cover in my offering to this annual advent calendar sits firmly in the middle. I can&#39;t prevent you from witnessing markup that makes you want to gouge your eyes out with rusty soup spoons, but I may have a solution that helps you understand what you can see in the browser a little more easily.&lt;/p&gt;
&lt;p&gt;Before I continue, it might be worth explaining a bit about what I do in my day-to-day role to provide context about why this all came about.&lt;/p&gt;
&lt;p&gt;I carry out accessibility audits for multiple clients at &lt;a href=&quot;https://tetralogical.com/about/&quot;&gt;TetraLogical&lt;/a&gt; (or &lt;a href=&quot;https://tetralogical.com/services/assessments/&quot;&gt;assessments&lt;/a&gt; as we refer to them internally). When I encounter something that doesn&#39;t behave as it should when trying to navigate using a keyboard, or doesn&#39;t sound right when using a screen reader, the first thing I need to check is what is the markup (HTML) behind the elements with issues. Typically, that means right-clicking on the part of the screen where the problem exists and looking at the &lt;strong&gt;Elements&lt;/strong&gt; tab in the browser&#39;s built-in DevTools feature. I&#39;m also likely to need to check the &lt;strong&gt;Accessibility&lt;/strong&gt; panel in DevTools to see what that markup exposes to assistive technology users.&lt;/p&gt;
&lt;p&gt;Here&#39;s a supoer simple example of TetraLogical&#39;s website, showing details of the top navigation element:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/DevTools-with-elements-and-accessibility-panels-information-highlighted.png&quot; alt=&quot;The Elements panel is showing, as well as the Accessibility panel. The header navigation, implemented as a  element shows clean, simple markup and also reveals its navigation role and its accessible name in the Accessibility panel&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What I hope to see whan I check the markup showing in DevTools: semantic markup that provides structure/meaning to what is rendered on the page (as in the example above).&lt;/li&gt;
&lt;li&gt;What I increasingly find: non-semantic markup that is often heavily nested, stuffed full of attributes, and which usually requires multiple steps to expand each node to get the full picture.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few years back, I created a tool that was very much borne out of frustration while doing an audit of a very well known web site. Everything that I checked was just an &lt;a href=&quot;https://www.tpgi.com/seeing-the-wood-for-the-trees-demystifying-markup-in-2021/&quot;&gt;absolute WALL of attribute-laden markup&lt;/a&gt;.&lt;br /&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/markup-de-wall-of-tags-and-attributes.png&quot; alt=&quot;Example of some markup that is almost impossible to decipher because it is completely overloaded with CSS classes and other attributes&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The markup might have been structurally fine, but it really took some effort to discern that that was the case. I had to go through various passes to work out what I was actually looking at to be able to make sense of things. The frustration led me to create the &lt;a href=&quot;https://a11y-tools.com/markup-de-crapulator/&quot;&gt;HTML De-crapulator&lt;/a&gt;, a tool that I would use many, many times in audits that I carried out for years after. But ... I still felt it could be more useful.&lt;/p&gt;
&lt;p&gt;The HTML De-Crapulator can provide many ways to simplify markup, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Removing specific attributes&lt;/li&gt;
&lt;li&gt;Abbreviating specific attributes&lt;/li&gt;
&lt;li&gt;Removing empty tags&lt;/li&gt;
&lt;li&gt;Removing framework-specific comment tags&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/de-crapulator.png&quot; alt=&quot;The HTML De-Crapulator interface, showing the input, some filtering options and the generated output&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Most of the time, pressing the &#39;Check (almost) all of the above&#39; button did the bulk of what is needed to strip selected markup to its bare bones. &lt;em&gt;Most of the time&lt;/em&gt; ... Inevitably, with each new site I had to check, I&#39;d find a new collection of custom attributes or tagnames that the tool didn&#39;t have in its defaults, so I&#39;d have to customise again and again. The tool does take out a lot of the manual work required to clean up the markup, but I was still finding it to not be as quick as it could be.&lt;br /&gt;
What do I want? I want to look at how a given part of the page is built, quickly. Yet &lt;em&gt;this&lt;/em&gt; still doesn&#39;t feel all that speedy to me:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Right click on an element on the page&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Inspect&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Right click on the node revealed in the &lt;strong&gt;Elements&lt;/strong&gt; panel in Dev tools&lt;/li&gt;
&lt;li&gt;Copy the Outer HTML&lt;/li&gt;
&lt;li&gt;Go to the HTML De-Crapulator and paste&lt;/li&gt;
&lt;li&gt;Try the &lt;strong&gt;Check (almost) all of the above&lt;/strong&gt; button and see what the results are&lt;/li&gt;
&lt;li&gt;Get frustrated by the remnants still there that I really don&#39;t care about&lt;/li&gt;
&lt;li&gt;Refine, refine, refine until I have the cleaned up markup just so&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I just wanted to get the markup that &lt;strong&gt;matters&lt;/strong&gt;, quickly. What do I mean by markup that matters?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Anything that exposes the &lt;code&gt;role&lt;/code&gt; of an element to assistive technology users&lt;/li&gt;
&lt;li&gt;Anything that exposes the state of an element to assistive technology users&lt;/li&gt;
&lt;li&gt;Any attribute that may affect the focusability of an element&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anything else is just noise. With that in mind, a few months back I came up with the &lt;a href=&quot;https://a11y-tools.com/bookmarklets/#one-click-decrapulator&quot;&gt;1-Click De-Crapulator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/one-click-decrapulator.png&quot; alt=&quot;Maybe make this one decorative with empty alt?&quot; /&gt;&lt;/p&gt;
&lt;p&gt;How does it work? You run the script (as a bookmarklet or you can use &lt;a href=&quot;https://chromewebstore.google.com/detail/a11y-tools-bookmarklets/fedddpaapeedmkanpenidomfbebacgoa&quot;&gt;the version in the Chrome extension&lt;/a&gt; if you prefer) and then do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click on the thing you want to get simplified markup for&lt;/li&gt;
&lt;li&gt;That&#39;s it. There is no step 2&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;OK, so there &lt;em&gt;sort of&lt;/em&gt; is a step 2 ... if you need it, and that&#39;s to copy the markup that&#39;s presented. But essentially, with one click you can see the markup for the selected node in a super-simplified format, ready to copy and paste if you choose to.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/1-selecting-HTML-node.png&quot; alt=&quot;With the 1-Click De-Crapulator running, you hover over the part of the page that you want to inspect, and it shows a border around the current node, as well as an information panel that provides info about the current HTML tag&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/2-decrapulated-markup.png&quot; alt=&quot;The tool shows the cleaned up markup in a dialog with buttons that read &#39;Close&#39;, &#39;Pick again&#39;, Flatten&#39; and &#39;Show Original&#39;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;At a glance, you can understand the structure of the item that you selected. All classes and trivial attributes are jettisoned. Only those that may have an impact on how the page is exposed to assistive technology users remain (text alternatives, states, &lt;code&gt;ARIA-*&lt;/code&gt; attributes, &lt;code&gt;id&lt;/code&gt; attributes ... but only where something else is referencing that element and needs it otherwise all the &lt;code&gt;id&lt;/code&gt;s are stripped).&lt;/p&gt;
&lt;p&gt;Went too far? You can also quickly switch between the original markup with all attributes intact, should you want to make a quick comparison.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/3-original-markup.png&quot; alt=&quot;The same dialog but showing the original markup, indented. The &#39;Show original&#39; button is indicated as pressed with a change of colour and a tick&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Didn&#39;t go far enough? Perhaps you&#39;re seeing endless levels of &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; nesting that really isn&#39;t contributing to meaning or structure? You have the option of flattening it. Here&#39;s the before version:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/4-flattened-markup-before.png&quot; alt=&quot;Example of markup with multiple layers of nested DIV elements&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And here is the after:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/13/5-flattened-markup-after.png&quot; alt=&quot;The same markup but with all needless nested DIV elements removed, showing the much more simplified structure&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Of course, you really are messing with the original markup here, but for the noble reasons of making it understandable and simplified. To save you having to explain each and every time that you simplified the markup when writing up an issue, the tool also wraps the output with Markdown block code backticks and an explanatory phrase that should work for almost every scenario: &amp;quot;Simplified HTML (with some attributes/features removed for clarity)&amp;quot;.&lt;/p&gt;
&lt;p&gt;As with the original full-fat HTML De-Crapulator, this won&#39;t address the root of the problem: namely, developers producing shoddy markup. But if you spend much of your day trying to decipher and remediate other people&#39;s markup, which can be hell, this tool can save you a lot of fuss and bother in getting to the bottom of the issue.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>A11y Considerations in Math on the Web</title>
    <link href="https://htmhell.dev/adventcalendar/2025/12/"/>
    <updated>2025-12-12T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/12/</id>
    <content type="html">by Manuel Sánchez&lt;br&gt;&lt;p&gt;Maybe it has happened to you that you wanted to write some formulas in HTML to display on a website, and even though there are multiple ways to do it, accessibility is often not considered in the process. How the formula is read by screen readers is crucial to ensure that we don&#39;t leave anyone behind. And the main assistive technologies are in different stages, as we will see.&lt;/p&gt;
&lt;p&gt;The web is full of many different and interesting approaches for representing formulas. To name a few, we have TeX/LaTeX source rendered in the browser in different ways, like MathJax or KaTeX, we can use Unicode math, Canvas/WebGL or even simple PNG/JPG or SVG pictures. However, using native &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/MathML&quot;&gt;MathML&lt;/a&gt; is usually one of the best options for this task, even if it wasn’t initially designed for the web. Some of its advantages are that it has its own syntax, MathML, which provides various elements that give the correct semantics to the different parts of a formula, it has good screen reader support, works without JavaScript dependencies, and can be used beyond the browser, as in EPUB or braille/math speech tooling.&lt;/p&gt;
&lt;p&gt;Let&#39;s take the famous Pythagorean Theorem as an example.&lt;/p&gt;
&lt;section style=&quot;margin-bottom: 2rem&quot; aria-labelledby=&quot;section-0-heading&quot;&gt;
  &lt;h2 id=&quot;section-0-heading&quot;&gt;Pythagorean Theorem&lt;/h2&gt;
  &lt;p&gt;The following example is a visual representation of the formula together with the MathML code.&lt;/p&gt;
  &lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;
    &lt;msup&gt;
      &lt;mi&gt;a&lt;/mi&gt;
      &lt;mn&gt;2&lt;/mn&gt;
    &lt;/msup&gt;
    &lt;mo&gt;+&lt;/mo&gt;
    &lt;msup&gt;
      &lt;mi&gt;b&lt;/mi&gt;
      &lt;mn&gt;2&lt;/mn&gt;
    &lt;/msup&gt;
    &lt;mo&gt;=&lt;/mo&gt;
    &lt;msup&gt;
      &lt;mi&gt;c&lt;/mi&gt;
      &lt;mn&gt;2&lt;/mn&gt;
    &lt;/msup&gt;
  &lt;/math&gt;
&lt;/section&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;math&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/1998/Math/MathML&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;=&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;c&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;math&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unlike plain HTML with &lt;code&gt;sup&lt;/code&gt; or &lt;code&gt;span&lt;/code&gt;, which only describe presentation, MathML defines each role explicitly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;math&lt;/code&gt; represents the entire mathematical expression.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;msup&lt;/code&gt; defines a superscript relationship (a base and an exponent).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mi&lt;/code&gt; is a mathematical identifier, typically a variable such as &lt;strong&gt;a&lt;/strong&gt;, &lt;strong&gt;b&lt;/strong&gt;, or &lt;strong&gt;c&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mn&lt;/code&gt; is a mathematical number, like &lt;strong&gt;2&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mo&lt;/code&gt; is a mathematical operator, such as &lt;strong&gt;+&lt;/strong&gt; or &lt;strong&gt;=&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other alternatives, like the ones mentioned above, may offer similar capabilities, but they typically rely on an assistive or hidden MathML layer. In practice, MathML remains the only web-standard markup that expresses mathematical roles natively in the DOM.&lt;/p&gt;
&lt;p&gt;With this approach, the accessibility tree shows good semantics and VoiceOver knows well what to do.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accessibility tree view of a MathML formula showing nested semantic elements. The tree includes nodes such as MathMLMath, MathMLSup, MathMLIdentifier, MathMLNumber, and MathMLOperator, representing the structure of the equation a² + b² = c².&quot; src=&quot;https://htmhell.dev/adventcalendar/2025/12/mathml-a11y-tree.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;However, as we will see throughout the article, screen reader support for the &lt;code&gt;math&lt;/code&gt; tag varies across assistive technologies. VoiceOver seems to be doing a pretty good job, &lt;a href=&quot;https://www.freedomscientific.com/training/teachers/accessing-math-content-with-jaws-and-fusion/&quot;&gt;JAWS also makes it easy for both speech and braille&lt;/a&gt;, and &lt;a href=&quot;https://github.com/nvaccess/nvda/issues/17667&quot;&gt;NVDA needs an add-on to make it work called MathCat&lt;/a&gt; because if not, the &lt;code&gt;math&lt;/code&gt; tag will be ignored. A major pull request (&lt;a href=&quot;https://github.com/nvaccess/nvda/pull/18323&quot;&gt;#18323&lt;/a&gt;) was merged on 17 November 2025 which integrates MathCAT into NVDA core, meaning users won’t have to find/install a separate add-on to handle math.&lt;/p&gt;
&lt;section aria-labelledby=&quot;example-formula&quot;&gt;
  &lt;h3 id=&quot;example-formula&quot;&gt;How screen readers interpret the formula&lt;/h3&gt;
  &lt;details&gt;
    &lt;summary&gt;NVDA + Firefox (Windows with MathCAT add-on)&lt;/summary&gt;
    region a squared plus b squared is equal to c squared space
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;VoiceOver + Safari (Mac)&lt;/summary&gt;
    a squared + b squared = c squared, with 5 items, maths
  &lt;/details&gt;
  &lt;details style=&quot;margin-bottom: 2rem;&quot;&gt;
    &lt;summary&gt;VoiceOver + Safari (iOS)&lt;/summary&gt;
    a squared plus b squared equals c squared, Math
  &lt;/details&gt;
&lt;/section&gt;
&lt;video style=&quot;margin-bottom: 1rem;&quot; title=&quot;How VoiceOver interprets the formula on Safari&quot; controls=&quot;&quot; width=&quot;904&quot; height=&quot;680&quot;&gt;
  &lt;source src=&quot;https://htmhell.dev/adventcalendar/2025/12/pythagorean-theorem.mp4&quot; type=&quot;video/mp4&quot; /&gt;
&lt;/video&gt;
&lt;p&gt;Let&#39;s look at a more complicated case. Instead of just displaying the formula, let&#39;s see how to actually prove it and how screen readers will announce it.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;math&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;block&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;semantics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Step one --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mrow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;              &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;(&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;              &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;              &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;              &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;              &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mrow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;=&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;c&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;4&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;⋅&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;(&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mfrac&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mfrac&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;)&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Step two --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;=&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;c&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Step three --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;=&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;c&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;          &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mtable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;annotation&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/x-tex&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      \begin{aligned} (a + b)^2 &amp;amp;= c^2 + 4 \cdot \left( \frac{1}{2} ab \right)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      \\ a^2 + 2ab + b^2 &amp;amp;= c^2 + 2ab \\ a^2 + b^2 &amp;amp;= c^2 \end{aligned}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;annotation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;semantics&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;math&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;math style=&quot;margin-bottom: 2rem;&quot; display=&quot;block&quot;&gt;
  &lt;semantics&gt;
    &lt;mtable&gt;
      &lt;!-- Step one --&gt;
      &lt;mtr&gt;
        &lt;mtd&gt;
          &lt;msup&gt;
            &lt;mrow&gt;
              &lt;mo&gt;(&lt;/mo&gt;
              &lt;mi&gt;a&lt;/mi&gt;
              &lt;mo&gt;+&lt;/mo&gt;
              &lt;mi&gt;b&lt;/mi&gt;
              &lt;mo&gt;)&lt;/mo&gt;
            &lt;/mrow&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/msup&gt;
        &lt;/mtd&gt;
        &lt;mtd&gt;
          &lt;mo&gt;=&lt;/mo&gt;
        &lt;/mtd&gt;
        &lt;mtd&gt;
          &lt;msup&gt;
            &lt;mi&gt;c&lt;/mi&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/msup&gt;
          &lt;mo&gt;+&lt;/mo&gt;
          &lt;mn&gt;4&lt;/mn&gt;
          &lt;mo&gt;⋅&lt;/mo&gt;
          &lt;mo&gt;(&lt;/mo&gt;
          &lt;mfrac&gt;
            &lt;mn&gt;1&lt;/mn&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/mfrac&gt;
          &lt;mi&gt;a&lt;/mi&gt;
          &lt;mi&gt;b&lt;/mi&gt;
          &lt;mo&gt;)&lt;/mo&gt;
        &lt;/mtd&gt;
      &lt;/mtr&gt;
      &lt;!-- Step two --&gt;
      &lt;mtr&gt;
        &lt;mtd&gt;
          &lt;msup&gt;
            &lt;mi&gt;a&lt;/mi&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/msup&gt;
          &lt;mo&gt;+&lt;/mo&gt;
          &lt;mn&gt;2&lt;/mn&gt;
          &lt;mi&gt;a&lt;/mi&gt;
          &lt;mi&gt;b&lt;/mi&gt;
          &lt;mo&gt;+&lt;/mo&gt;
          &lt;msup&gt;
            &lt;mi&gt;b&lt;/mi&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/msup&gt;
        &lt;/mtd&gt;
        &lt;mtd&gt;
          &lt;mo&gt;=&lt;/mo&gt;
        &lt;/mtd&gt;
        &lt;mtd&gt;
          &lt;msup&gt;
            &lt;mi&gt;c&lt;/mi&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/msup&gt;
          &lt;mo&gt;+&lt;/mo&gt;
          &lt;mn&gt;2&lt;/mn&gt;
          &lt;mi&gt;a&lt;/mi&gt;
          &lt;mi&gt;b&lt;/mi&gt;
        &lt;/mtd&gt;
      &lt;/mtr&gt;
      &lt;!-- Step three --&gt;
      &lt;mtr&gt;
        &lt;mtd&gt;
          &lt;msup&gt;
            &lt;mi&gt;a&lt;/mi&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/msup&gt;
          &lt;mo&gt;+&lt;/mo&gt;
          &lt;msup&gt;
            &lt;mi&gt;b&lt;/mi&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/msup&gt;
        &lt;/mtd&gt;
        &lt;mtd&gt;
          &lt;mo&gt;=&lt;/mo&gt;
        &lt;/mtd&gt;
        &lt;mtd&gt;
          &lt;msup&gt;
            &lt;mi&gt;c&lt;/mi&gt;
            &lt;mn&gt;2&lt;/mn&gt;
          &lt;/msup&gt;
        &lt;/mtd&gt;
      &lt;/mtr&gt;
    &lt;/mtable&gt;
  &lt;/semantics&gt;
&lt;/math&gt;
&lt;p&gt;This proof example just added several MathML elements that go beyond simple identifiers and operators. Each of these adds meaning to the expression, which is why assistive technologies can navigate the structure so precisely. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;mtable&lt;/code&gt;, &lt;code&gt;mtr&lt;/code&gt; and &lt;code&gt;mts&lt;/code&gt;: these directly mirror HTML&#39;s &lt;code&gt;table&lt;/code&gt;, &lt;code&gt;tr&lt;/code&gt; and &lt;code&gt;td&lt;/code&gt; but are math-specific. They tell the accessibility tree: &amp;quot;this is a mathematical table with aligned steps,&amp;quot; not just a generic layout table. Screen readers can move row-by-row, so each step of the proof becomes navigable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;mrow&lt;/code&gt;: groups expressions together. For example &lt;code&gt;(a + b)&lt;/code&gt; is wrapped in an &lt;code&gt;mrow&lt;/code&gt; to indicate that the parentheses and the interior form a single unit before exponentiation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;mfrac&lt;/code&gt;: defines an actual mathematical fraction, not just text with a slash. This allows speech engines to say &amp;quot;one half&amp;quot; instead of &amp;quot;one over two&amp;quot; depending on preferences and locale.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;semantics&lt;/code&gt;: this is key. It wraps the expression and lets you attach alternative meanings or encodings. Assistive technologies prefer the first child (your visual MathML), but can fall back to the annotation if needed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;annotation&lt;/code&gt;: stores auxiliary information. In this case, the TeX version of the proof. It does not affect the visual rendering in the browser. Instead, it&#39;s metadata for tools that consume MathML, like converters, EPUB readers, or braille translators.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Check out how this is announced by different screen readers!&lt;/p&gt;
&lt;section aria-labelledby=&quot;example-proof&quot;&gt;
  &lt;h3 id=&quot;example-proof&quot;&gt;How screen readers interpret the proof&lt;/h3&gt;
  &lt;details&gt;
  &lt;summary&gt;NVDA + Firefox (Windows with MathCAT add-on)&lt;/summary&gt;
  3 lines
  line 1 left parenthesis a plus b right parenthesis squared is equal to c squared plus 4 times 1 half a b
&lt;p&gt;line 2 a squared plus 2 a b plus b squared is equal to c squared plus 2 a b&lt;/p&gt;
&lt;p&gt;line 3 a squared plus b squared is equal to c squared&lt;/p&gt;
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;VoiceOver + Safari (Mac)&lt;/summary&gt;
    Table start, Row 1, Column 1, ( a + b ) squared, Row 1, Column 2, =, Row 1, Column 3, c squared + 4 · ( fraction start, 1 over 2, end of fraction, a b ), Row 2, Column 1, a squared + 2 a b + b squared, Row 2, Column 2, =, Row 2, Column 3, c squared + 2 a b, Row 3, Column 1, a squared + b squared, Row 3, Column 2, =, Row 3, Column 3, c squared, table end, maths
  &lt;/details&gt;
  &lt;details style=&quot;margin-bottom: 2rem;&quot;&gt;
    &lt;summary&gt;VoiceOver + Safari (iOS)&lt;/summary&gt;
    1 table, table start, Row 1, Column 1, a plus b squared, Row 1, Column 2, equals, Row 1, Column 3, c squared plus 4 dot fraction start 1 over 2, end of fraction, a b, Row 2, Column 1, a squared plus 2 a b plus b squared, Row 2, Column 2, equals, Row 2, Column 3, c squared plus 2 a b, Row 3, Column 1, a squared plus b squared, Row 3, Column 2, equals, Row 3, Column 3, c squared, table end, Math
  &lt;/details&gt;
&lt;/section&gt;
&lt;video style=&quot;margin-bottom: 1rem;&quot; title=&quot;How VoiceOver interprets the proof formula on Safari&quot; controls=&quot;&quot; width=&quot;904&quot; height=&quot;680&quot;&gt;
  &lt;source src=&quot;https://htmhell.dev/adventcalendar/2025/12/pythagorean-theorem-proof.mp4&quot; type=&quot;video/mp4&quot; /&gt;
&lt;/video&gt;
&lt;p style=&quot;margin-top: 1rem;&quot; class=&quot;highlight&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you want to deepen your understanding in the topic, MDN has a very detailed page about &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/MathML/Guides/Proving_the_Pythagorean_theorem&quot;&gt;proving the Pythagorean theorem with MathML&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;some-a11y-enhancements&quot;&gt;Some A11y Enhancements&lt;/h2&gt;
&lt;p&gt;We could enhance this by adding an &lt;code&gt;aria-label&lt;/code&gt; to a wrapper that provides some information about the following formula, especially when it&#39;s a well-known one. By using a &lt;code&gt;section&lt;/code&gt; with an &lt;code&gt;aria-label&lt;/code&gt; or &lt;code&gt;aria-labelledby&lt;/code&gt; together with another element giving the accessible name, we automatically insert a region into the accessibility tree.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;section-1-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;section-1-heading&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Pythagorean Theorem&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;math&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/1998/Math/MathML&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; ... &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;math&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also, for users who zoom the browser up to 400%, we might want to add a &lt;code&gt;max-width: 100%&lt;/code&gt; and &lt;code&gt;overflow-x: auto&lt;/code&gt;, so that the formula remains readable, does not break the page and we allow horizontal scrolling only inside the math block, and not at the entire page level.&lt;/p&gt;
&lt;h2 id=&quot;conveying-mathematical-meaning-with-aria&quot;&gt;Conveying mathematical meaning with ARIA&lt;/h2&gt;
&lt;p&gt;We also have the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/math_role&quot;&gt;&lt;code&gt;math&lt;/code&gt; role&lt;/a&gt; from the ARIA specification. With that, we can communicate the mathematical semantics even when we rely on images or non-semantic HTML. However, it does not give good results with VoiceOver on macOS, for example.&lt;/p&gt;
&lt;p&gt;As shown on the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/math_role&quot;&gt;MDN page for the &lt;code&gt;math&lt;/code&gt; role&lt;/a&gt;, we could have:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;math&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-label&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;a^{2} + b^{2} = c^{2}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;sup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;sup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; + b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;sup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;sup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; = c&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;sup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;sup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;section aria-labelledby=&quot;example-div&quot;&gt;
  &lt;h3 id=&quot;example-div&quot;&gt;Markup with a div with the math role and how screen readers interpret it&lt;/h3&gt;
  &lt;details&gt;
    &lt;summary&gt;Markup&lt;/summary&gt;
    &lt;div style=&quot;margin-bottom: 2rem;&quot; role=&quot;math&quot; aria-label=&quot;a^{2} + b^{2} = c^{2}&quot;&gt;
      a&lt;sup&gt;2&lt;/sup&gt; + b&lt;sup&gt;2&lt;/sup&gt; = c&lt;sup&gt;2&lt;/sup&gt;
    &lt;/div&gt;
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;NVDA + Firefox (Windows with MathCAT add-on)&lt;/summary&gt;
  just announces the text
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;VoiceOver + Safari (Mac)&lt;/summary&gt;
    not read, just announces &quot;with 6 items, maths&quot;
  &lt;/details&gt;
  &lt;details style=&quot;margin-bottom: 2rem;&quot;&gt;
    &lt;summary&gt;VoiceOver + Safari (iOS)&lt;/summary&gt;
    a caret left curly bracket 2 right curly bracket plus b caret left curly bracket 2 right curly bracket equals c caret left curly bracket, Math
  &lt;/details&gt;
&lt;/section&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pythagorean_theorem.png&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;a^{2} + b^{2} = c^{2}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;math&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;section aria-labelledby=&quot;example-img&quot;&gt;
  &lt;h3 id=&quot;example-img&quot;&gt;Markup with a img with the math role and how screen readers interpret it&lt;/h3&gt;
  &lt;details&gt;
    &lt;summary&gt;Markup&lt;/summary&gt;
    &lt;img width=&quot;150&quot; alt=&quot;a^{2} + b^{2} = c^{2}&quot; src=&quot;https://htmhell.dev/adventcalendar/2025/12/pythagorean-theorem.png&quot; role=&quot;math&quot; /&gt;
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;NVDA + Firefox (Windows with MathCAT add-on)&lt;/summary&gt;
  just announces the text
  &lt;/details&gt;
  &lt;details&gt;
    &lt;summary&gt;VoiceOver + Safari (Mac)&lt;/summary&gt;
    not read, just announces &quot;maths&quot;
  &lt;/details&gt;
  &lt;details style=&quot;margin-bottom: 2rem;&quot;&gt;
    &lt;summary&gt;VoiceOver + Safari (iOS)&lt;/summary&gt;
    a caret left curly bracket 2 right curly bracket plus b caret left curly bracket 2 right curly bracket equals c caret left curly bracket, Math
  &lt;/details&gt;
&lt;/section&gt;
&lt;p&gt;In practice, using the math role helps assistive technologies understand that the content is mathematical, but it still doesn’t provide enough semantic detail for them to announce the expression as accurately as MathML does.&lt;/p&gt;
&lt;h2 id=&quot;the-future-of-mathml&quot;&gt;The future of MathML&lt;/h2&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;&lt;abbr title=&quot;too long; didn&#39;t read&quot;&gt;TL;DR:&lt;/abbr&gt;&lt;/strong&gt; MathML Core is what browsers implement today; MathML 4 is the broader language evolving around it.&lt;/p&gt;
&lt;p&gt;As I mentioned at the beginning, the origin of MathML was not the web, it was more of a general-purpose specification for browsers, office suites, computer algebra systems, EPUB readers, and LaTeX-based generators, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/MathML&quot;&gt;as stated on MDN&lt;/a&gt;. MathML Core arose from the need to make it work with web standards, including HTML, CSS, DOM, and JavaScript. Historically, the full MathML spec was broad and partly underspecified for browsers, which led to uneven or incomplete implementations across engines. MathML Core therefore narrows the language to the subset that can be precisely defined on top of the Web Platform, improving testability and cross-browser interoperability. Since June 2025, MathML Core has been a &lt;a href=&quot;https://www.w3.org/TR/2025/CR-mathml-core-20250624/&quot;&gt;Candidate Recommendation Snapshot&lt;/a&gt;. On another note, at the time of this writing, there is &lt;a href=&quot;https://www.w3.org/TR/mathml4/&quot;&gt;a Working Draft for MathML 4&lt;/a&gt;, the next version of MathML. This version aims to be the next &amp;quot;full&amp;quot; spec that extends Core. It keeps the larger feature set (e.g., Content MathML) and adds, among others, the &lt;code&gt;intent&lt;/code&gt; attribute so authors can guide screen-reader speech. With it, we&#39;ll be able to do something like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;math&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mrow&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;intent&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;equals(power(a,2)+power(b,2),power(c,2))&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;b&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;=&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;c&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;msup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;mrow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;math&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As &lt;a href=&quot;https://caniuse.com/mathml&quot;&gt;browser support for MathML continues to evolve&lt;/a&gt;, previous fallback solutions like &lt;a href=&quot;https://github.com/fred-wang/mathml.css&quot;&gt;mathml.css&lt;/a&gt; are no longer necessary. MathML Core, and soon MathML 4, allow us to express both the visual and semantic meaning of mathematical content without sacrificing accessibility along the way.&lt;/p&gt;
&lt;p&gt;Screen-reader support is also steadily improving. Each assistive technology handles MathML in its own way, but the overall trajectory is positive. VoiceOver offers consistent navigation and speech for many common patterns across macOS and iOS. JAWS, especially when paired with Fusion, provides rich support for both speech and braille. And NVDA, which historically required an add-on, is now moving toward a built-in MathCAT integration, making MathML speech and braille support more accessible out of the box for Windows users.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>How HTML changes in ePub</title>
    <link href="https://htmhell.dev/adventcalendar/2025/11/"/>
    <updated>2025-12-11T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/11/</id>
    <content type="html">by Robin Whittleton&lt;br&gt;&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/epub-33/&quot;&gt;ePub&lt;/a&gt; is the W3C standard for ebooks. It lets you take your knowledge of the web, and use it to produce little self-contained sets of documents that can be freely distributed as a single file ready for reading on extremely low-power devices, and they even reflow to fit any screen.&lt;/p&gt;
&lt;p&gt;Yet while I said that you can use your knowledge of the web to build ePubs, the technology in use is twisted in unforeseen ways, and you might have to unlearn the things you think you knew. Prepare yourself…&lt;/p&gt;
&lt;h2 id=&quot;html-sort-of&quot;&gt;HTML, sort of&lt;/h2&gt;
&lt;p&gt;ePubs, at their core, use HTML, just like the websites we build every day. Except, well, there’s a big asterisk after that. Let’s dive into the differences.&lt;/p&gt;
&lt;p&gt;A few decades ago &lt;a href=&quot;https://www.w3.org/TR/xml/&quot;&gt;XML&lt;/a&gt; emerged from the pit. XML – an extensible standard for expressing marked up data – could be used for documents, data transfer, and a bunch of other things, and people genuinely liked it (or, much like AI today, pretended to for job security). They liked it so much that a concerted effort was started to take HTML and rebuild it on top of XML. This project had a name you might have heard of: &lt;a href=&quot;https://www.w3.org/TR/xhtml11/&quot;&gt;XHTML&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;XHTML didn’t work out, for a number of reasons. The extensibility of XML turned out to not be useful when browsers didn’t support even common extensions. Then there was the problem of fragility: any syntax problems with your XHTML and your users would get a blank screen. If those two problems weren’t enough, XHTML was slower in practice because the browser needed to wait to download the entire document before doing anything else.&lt;/p&gt;
&lt;p&gt;But there is one place where XHTML still rules the roost: ePub. ePub books are, at their heart, a collection of XHTML documents (now using &lt;a href=&quot;https://html.spec.whatwg.org/#html-vs-xhtml&quot;&gt;the XHTML flavour of the HTML Living Standard&lt;/a&gt;). This means that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Valid, syntactically correct XML markup is needed. Without that, your e-reader will complain. This means self-closing tags, correct namespaces, XML attributes in the XML namespace (&lt;code&gt;xml:lang&lt;/code&gt;), and so on.&lt;/li&gt;
&lt;li&gt;Other XML languages can be included directly into XHTML by adding namespaces.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;epub&lt;/code&gt; namespace is unlocked, which adds additional functionality to your ePub in e-readers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We’ll come back to that…&lt;/p&gt;
&lt;h2 id=&quot;css-sort-of&quot;&gt;CSS, sort of&lt;/h2&gt;
&lt;p&gt;So HTML is actually XHTML in ePub. Is CSS some sort of XCSS? Actually, no: CSS is broadly the same as you know it, but with a few quirks.&lt;/p&gt;
&lt;p&gt;First up, e-readers and e-reader software are, compared to our normal evergreen browsers, typically really basic. They can run on underpowered hardware, people often keep their e-readers for over a decade, and the engines they use can be positively historic. To put it another way, I’m wary of using &lt;code&gt;:not()&lt;/code&gt; in ePub CSS for a widely distributed title. While I might be overly cautious here, don’t expect nowadays normal pseudoclasses like &lt;code&gt;:is()&lt;/code&gt; to have wide support. Luckily, layout tends to be simpler in a document-focused format, and progressive enhancement is possible with &lt;code&gt;@supports&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, as our markup is now namespace aware, our CSS needs to follow. For example, if you wanted to style a piece of text in a different language that you’ve marked up like:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;As Jean-Paul Sartre said, &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;q&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xml:&lt;/span&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;fr&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;L’enfer, c’est les autres&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;q&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can’t simply use an attribute selector like &lt;code&gt;q[lang]&lt;/code&gt;, you need to define your namespaces and reference them in your selectors using the &lt;code&gt;|&lt;/code&gt; separator:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@namespace&lt;/span&gt; xml &lt;span class=&quot;token string&quot;&gt;&quot;http://www.w3.org/XML/1998/namespace&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;q[xml|lang]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;strange-extensions&quot;&gt;Strange extensions&lt;/h2&gt;
&lt;p&gt;As mentioned earlier, namespace support means that other XML-compatible markup languages can be incorporated directly into your XHTML document. These could be just additional semantic attributes, or even new elements. Obviously to get anything useful out of them you need e-reader support, but that’s present in a few cases. Let’s take a look at a couple.&lt;/p&gt;
&lt;p&gt;You might actually be familiar with &lt;a href=&quot;https://htmhell.dev/adventcalendar/2025/12/&quot;&gt;MathML&lt;/a&gt;, as it’s &lt;a href=&quot;https://html.spec.whatwg.org/#mathml&quot;&gt;supported in HTML5&lt;/a&gt;. The way you use it in HTML is that there’s a broad agreement that the contents of the MathML spec will just work when used in HTML. Adding a basic MathML equation using standard MathML tags (&lt;code&gt;math&lt;/code&gt;, &lt;code&gt;mi&lt;/code&gt;, &lt;code&gt;mo&lt;/code&gt;, &lt;code&gt;mn&lt;/code&gt;, and so on) to your normal HTML document ends up looking something like &lt;math alttext=&quot;n + 1&quot;&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;/math&gt;.&lt;/p&gt;
&lt;p&gt;But in XHTML (because it’s an XML language) there’s a standard integration process for any XML language you want to bring in. First, you define your MathML namespace against the root element:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/1999/xhtml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xmlns:&lt;/span&gt;m&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/1998/Math/MathML&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the MathML elements are available to use inside the document under that namespace:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;m:&lt;/span&gt;math&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alttext&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;n + 1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;m:&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;n&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;m:&lt;/span&gt;mi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;m:&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;+&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;m:&lt;/span&gt;mo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;m:&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;m:&lt;/span&gt;mn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;m:&lt;/span&gt;math&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Same goes for SVG: in HTML &lt;a href=&quot;https://html.spec.whatwg.org/#svg-0&quot;&gt;it’s just allowed to be included&lt;/a&gt; with standard SVG tags; using &lt;code&gt;svg&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;path&lt;/code&gt; can get you something like &lt;svg style=&quot;height: 1em&quot; viewBox=&quot;0 0 452 452&quot;&gt;&lt;title&gt;the HTMHell logo&lt;/title&gt;&lt;path d=&quot;M198.2.94c-28.6 3.3-61.4 14.6-87.3 29.9-61.2 36.2-102.2 99.8-110 170.8-1.8 16-.8 47.3 1.9 62.7 5.3 29.9 17 59.3 33.9 85 68.8 105 209.3 133.9 314 64.5 33.9-22.5 60.3-52.7 78.2-89.5 10.5-21.5 16.5-40.6 20.7-66 2.4-15 2.4-48.2-.1-64.5-7.9-51.9-30.4-95.7-67.7-131.5-35.6-34.2-82.3-56.2-130.1-61.4-11.2-1.3-42.9-1.2-53.5 0m55.2 19.4c14.7 2.1 23.7 4.1 36 8.1 11.9 3.9 34.9 14.5 45.9 21.3l6.9 4.3 7.4-5.2c4.1-2.9 7.6-5 7.9-4.7.3.2-.7 4-2.1 8.3-1.3 4.4-2.5 8.2-2.5 8.5s4.9 4.9 10.9 10.2c48.3 42.8 74.5 109.7 68.1 173.8-.9 8.8-4.2 26.9-6.5 36-.6 2.3.1 3 7.1 8l7.7 5.4-9.6.3-9.6.3-1.9 5.2c-11.5 30.5-33.6 61.5-59 82.8-32.1 26.8-70.7 43.8-109.2 47.9-5.8.6-12.4 1.3-14.7 1.6l-4.2.5-2.7 8.2c-1.4 4.5-3 8.5-3.3 9-.4.4-2-3.3-3.6-8.2l-2.8-9-4.6-.5c-2.5-.3-7.7-.8-11.6-1.1-18.2-1.6-42.2-8.1-62.2-16.9-47.2-20.6-88.8-63.8-107.4-111.1-1.3-3.3-2.7-6.5-3.2-7.2-.6-.8-4.3-1.3-10-1.5l-9.1-.3 7.6-5.7 7.6-5.7-1.8-6.8c-5.3-20.1-7.5-52.2-5.1-73.4 5.3-45.8 24.7-87.2 56.5-120.6 5.4-5.7 12.7-12.6 16.2-15.4 5.4-4.3 6.3-5.5 5.8-7.3-3.9-11.8-5.1-16.5-4.1-16 .7.4 4.2 2.9 7.9 5.6 3.7 2.6 7 4.8 7.4 4.8.3 0 2.4-1.3 4.7-2.9 6.9-4.7 20.5-11.7 32.2-16.6 17.5-7.3 36.5-12.3 57-14.8 8.3-1.1 40.9-.5 50 .8&quot;&gt;&lt;/path&gt;&lt;path fill=&quot;#d72b2b&quot; d=&quot;M165.9 218.04c-3 2.1-5.9 4.3-6.3 4.8-.5.4 14.1 47 32.4 103.4s33.7 102.2 34 101.8c.8-.7 42.9-129.9 42.9-131.3 0-.5-3.5-.9-7.8-.9h-7.8l-13.5 41.5c-7.4 22.8-13.7 41.5-14 41.5s-12.4-36.6-26.9-81.3c-14.5-44.6-26.6-81.7-26.9-82.3-.4-.8-2.5.2-6.1 2.8m137.7-4.7-2.5 7.5 35.4 25.7 35.5 25.8-86.6.3c-65.4.1-86.5.5-86.5 1.4 0 .6 1 4.2 2.2 8l2.2 6.8h217.8l-57.1-41.5c-31.5-22.8-57.3-41.5-57.5-41.5s-1.6 3.4-2.9 7.5m-184.8 11.3-87.6 63.7 70 .3c38.5.1 70.2 0 70.5-.2.2-.3-.7-3.8-1.9-7.8l-2.4-7.3-43.9-.5-44-.5 68.5-49.7c37.6-27.3 69.2-50.3 70.2-51 1.7-1.2 1.3-1.8-4.8-6.1-3.6-2.6-6.6-4.7-6.8-4.7-.1.1-39.6 28.8-87.8 63.8m169.8-123.5-56.7 41.2 2.7 2.3c1.6 1.2 4.5 3.4 6.5 4.8l3.8 2.7 6.7-5c37.2-27 64.4-46.5 64.7-46.2.1.2-11.8 37.5-26.6 82.9-14.7 45.4-26.8 82.6-26.8 82.8s3.6.2 8.1 0l8.1-.3 33.4-102.9c18.4-56.6 33.3-103 33.2-103.2-.2-.1-25.9 18.3-57.1 40.9m-182.7-40.8c0 1.1 42 130.7 42.9 132.3.5.9 2.5-.1 6.9-3.4 3.4-2.5 6.2-4.9 6.2-5.2 0-.4-6.1-19.1-13.5-41.7-7.4-22.5-13.2-41.1-13-41.3s31.6 22.4 69.9 50.2 70 50.6 70.4 50.6c.7 0 5.2-12.4 5.2-14.3 0-.3-37.9-28.2-84.2-61.8-46.4-33.7-85.8-62.3-87.5-63.7-1.8-1.3-3.3-2.1-3.3-1.7&quot;&gt;&lt;/path&gt;&lt;/svg&gt;. But in XHTML you’ll need to declare the SVG namespace and use that with your images:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/1999/xhtml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xmlns:&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2000/svg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;svg:&lt;/span&gt;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;viewBox&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0 0 452 452&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;svg:&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;the HTMHell logo&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;svg:&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;svg:&lt;/span&gt;path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;M198.2.94c-28.6 3.3-61.4…&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;svg:&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course, we’re talking about ePub here. There’s a &lt;a href=&quot;https://www.w3.org/TR/epub-33/&quot;&gt;W3 ePub specification (currently at version 3.3)&lt;/a&gt; that defines the structure and metadata of an ePub document, and gives us the &lt;a href=&quot;https://www.w3.org/TR/epub-33/#dfn-epub-type&quot;&gt;&lt;code&gt;epub:type&lt;/code&gt; attribute&lt;/a&gt;. This attribute (in conjunction with the &lt;a href=&quot;https://www.w3.org/TR/epub-ssv-11/&quot;&gt;Structural Semantics Vocabulary specification&lt;/a&gt;) can be used in a few ways to improve your collection’s usability within an e-reader. Let’s look at an example.&lt;/p&gt;
&lt;p&gt;One thing books often have is endnotes, but there’s no easy way of expressing that semantic state in HTML. In ePub’s vocabulary though we find the &lt;a href=&quot;https://www.w3.org/TR/epub-ssv-11/#noteref&quot;&gt;&lt;code&gt;noteref&lt;/code&gt; attribute value&lt;/a&gt;. If we use this on a link then readers know to pull in a fragment from another place and typically display then this inside a modal that can be dismissed to return to the existing place. This looks something like:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;ePub is hellish.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;endnotes.xhtml#note-1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;noteref-1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;epub:&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;noteref&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And in your collection of endnotes:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;note-1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;epub:&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;endnote&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;…unless you read HTMHell. &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;page.xhtml#noteref-1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;epub:&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;backlink&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;↩&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;epub:type&lt;/code&gt; is gradually being deprecated in favour of the &lt;code&gt;role&lt;/code&gt; values defined in the &lt;a href=&quot;https://www.w3.org/TR/dpub-aria-1.1/&quot;&gt;Digital Publishing WAI-ARIA spec&lt;/a&gt;, but currently that functionality is either unimplemented or only available in the latest systems. For example, the above endnotes functionality doesn’t yet work in Apple Books (generally a good e-reader) if you use &lt;code&gt;role=&quot;doc-noteref&quot;&lt;/code&gt; and &lt;code&gt;role=&quot;doc-endnotes&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As well as these ePub semantic vocabulary, we also have things like the &lt;a href=&quot;https://www.daisy.org/z3998/2012/vocab/structure/&quot;&gt;Z39.98-2012 Structural Semantics Vocabulary&lt;/a&gt;. This extends the base ePub spec, and takes the form of &lt;code&gt;z3998&lt;/code&gt;-namespaced attribute &lt;em&gt;values&lt;/em&gt;, which definitely looks odd if you’re not used to it. You can use these to express even more fine-grained semantic values, for example &lt;a href=&quot;https://www.daisy.org/z3998/2012/vocab/structure/#roman&quot;&gt;Roman numerals&lt;/a&gt; (&lt;code&gt;&amp;lt;span epub:type=&amp;quot;z3998:roman&amp;quot;&amp;gt;DCLXVI&amp;lt;/span&amp;gt;&lt;/code&gt;) or &lt;a href=&quot;https://www.daisy.org/z3998/2012/vocab/structure/#h_letters&quot;&gt;parts of letters&lt;/a&gt;. Broad support for extracting any functionality from these is extremely lacking, but when did that ever stop us front-end developers from going over the top?&lt;/p&gt;
&lt;h2 id=&quot;want-to-try-this-all-out?&quot;&gt;Want to try this all out?&lt;/h2&gt;
&lt;p&gt;Writing an ePub isn’t exactly hard, but there’s some scaffolding necessary to get to a workable structure. You need a &lt;a href=&quot;https://www.w3.org/TR/epub-33/#sec-container-metainf-container.xml&quot;&gt;&lt;code&gt;container.xml&lt;/code&gt; file&lt;/a&gt; in a &lt;code&gt;META-INF&lt;/code&gt; directory that points at &lt;a href=&quot;https://www.w3.org/TR/epub-33/#sec-package-doc&quot;&gt;a package file&lt;/a&gt;. The package file contains a bunch of metadata about your ePub, including &lt;a href=&quot;https://www.w3.org/TR/epub-33/#sec-pkg-manifest&quot;&gt;a manifest&lt;/a&gt; of the XHTML files in your book (for example, different chapters), and &lt;a href=&quot;https://www.w3.org/TR/epub-33/#sec-pkg-spine&quot;&gt;a spine&lt;/a&gt; describing the order they should be shown to the reader. You then add your XHTML files, reference them in the manifest and spine, and finally zip the whole directory up into a single archive and rename it to a &lt;code&gt;.epub&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To get you started, I’ve prepared &lt;a href=&quot;https://htmhell.dev/adventcalendar/2025/11/htmhell-2025-12-11.epub&quot;&gt;a copy of this blog post as an ePub&lt;/a&gt; ready for your favourite e-reader (assuming it’s modern: I haven’t included any compatibility hacks). To inspect the contents we just need to unzip it; try renaming the file to have a &lt;code&gt;.zip&lt;/code&gt; at the end and opening it with your favourite unarchiver. The markup can be found in &lt;code&gt;src/epub/text&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to create your own ePubs I’d personally recommend starting with &lt;a href=&quot;https://github.com/standardebooks/tools&quot;&gt;the Standard Ebooks toolset&lt;/a&gt;: it can create unbranded ePubs and has a bunch of compatibility tooling built in. Once installed, you can create a directory with the requisite scaffolding with &lt;code&gt;se create-draft --white-label&lt;/code&gt;, and then build that into an ePub with &lt;code&gt;se build&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I hope you have fun putting your own ebooks together! It’s a useful new skill that reuses a lot of your existing knowledge.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>a11y freedom beaver</title>
    <link href="https://htmhell.dev/adventcalendar/2025/10/"/>
    <updated>2025-12-10T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/10/</id>
    <content type="html">by Steve Faulkner&lt;br&gt;&lt;p&gt;&lt;span role=&quot;img&quot; aria-label=&quot;Accessibility Freedom Beaver&quot;&gt;♿☮️🦫&lt;/span&gt; sez: &lt;a href=&quot;https://html5accessibility.com/stuff/2020/11/24/know-your-standards/&quot;&gt;Know your Standards&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/bab8c885-0635-4a0c-82b7-ccb3004c1b95&quot; alt=&quot;SAY &#39;ARIA TAG&#39; AGAIN Side profile pic of Adrian looking menacing with a mouse cursor &#39;tattoo&#39; below his eye&quot; width=&quot;297&quot; height=&quot;398&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;1st-rule-of-aria&quot;&gt;1st Rule of ARIA&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;first rule&lt;/strong&gt; originally appeared in 2012 &lt;a href=&quot;https://www.tpgi.com/html5-accessibility-chops-using-aria-notes/&quot;&gt;Notes on using ARIA&lt;/a&gt;, it was then moved to a new home &lt;a href=&quot;https://w3c.github.io/using-aria/#rule1&quot;&gt;Using ARIA&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&#39;s not really a &lt;strong&gt;rule&lt;/strong&gt; in any formal sense; I just made it up. It has remained unchanged for 14 years but remains relevant today.&lt;/p&gt;
&lt;blockquote class=&quot;blockquote-no-quotes&quot;&gt;
&lt;p&gt;&lt;strong&gt;First Rule of ARIA Use&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you can use a native HTML element &lt;a href=&quot;https://html.spec.whatwg.org/multipage/&quot;&gt;HTML&lt;/a&gt; or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Under what circumstances may this not be possible?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the feature is available in &lt;a href=&quot;https://html.spec.whatwg.org/multipage/&quot;&gt;HTML&lt;/a&gt; but it is not implemented or it is implemented, but accessibility support is not&lt;/li&gt;
&lt;li&gt;If the visual design constraints rule out the use of a particular native element, because the element cannot be styled as required&lt;/li&gt;
&lt;li&gt;If the feature is not currently available in &lt;a href=&quot;https://html.spec.whatwg.org/multipage/&quot;&gt;HTML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;source: &lt;cite&gt;&lt;a href=&quot;https://w3c.github.io/using-aria/#rule1&quot;&gt;Using ARIA&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;h3 id=&quot;reasons-to-be-cheerful-(about-not-having-to-use-aria-so-much)&quot;&gt;Reasons to be cheerful (about not having to use ARIA so much)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;the feature is available in &lt;a href=&quot;https://html.spec.whatwg.org/multipage/&quot;&gt;HTML&lt;/a&gt; but it is not implemented or it is implemented, but accessibility support is not&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When I first wrote the first rule there were many new features in HTML, many of which had not had their accessibility support (or support in general) wired up. Which is why I started documenting support for new features back in 2010 (&lt;a href=&quot;https://web.archive.org/web/20101011095344/http://www.html5accessibility.com/&quot;&gt;HTML5Accessibility.com WayBack Machine snapshot October 2010&lt;/a&gt;). Last time I checked back in &lt;a href=&quot;https://html5accessibility.com/&quot;&gt;August 2020&lt;/a&gt;, things were looking much better. So these days there is little to no need to use ARIA to supplement native HTML semantics, the browsers do it for you &lt;em&gt;mostly&lt;/em&gt;. In fact the &lt;strong&gt;unecessary use of ARIA&lt;/strong&gt; is a HTML conformance error as defined in the &lt;a href=&quot;https://w3c.github.io/html-aria/#docconformance&quot;&gt;ARIA in HTML&lt;/a&gt; specification.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;visual design constraints rule out the use of a particular native element, because the element cannot be styled as required&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In 2025 the opportunity for a front end developer to craft visual UI that meets the needs of their bosses is much improved. CSS and browser implementations continue to be enhanced to make it possible.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;the feature is not currently available in &lt;a href=&quot;https://html.spec.whatwg.org/multipage/&quot;&gt;HTML&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is still a valid reason for building stuff from HTML elements that carry little or no semantics, then adding ARIA to convey meaning robustly and interoperably to people that make use of assistive technology to render web content understandable. But valid &lt;em&gt;less so&lt;/em&gt; as many of the features that are routinely foisted upon users are now available as native HTML, for example, &lt;a href=&quot;https://html.spec.whatwg.org/multipage/interactive-elements.html#the-dialog-element&quot;&gt;dialogs&lt;/a&gt; and &lt;a href=&quot;https://html.spec.whatwg.org/multipage/interactive-elements.html#the-details-element&quot;&gt;disclosures&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-aria-does-not-do&quot;&gt;What ARIA does not do&lt;/h2&gt;
&lt;p&gt;The good thing about using HTML elements is they have operability built in: &lt;strong&gt;ARIA does not&lt;/strong&gt;.&lt;br /&gt;
For example, a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;-element is automatically included in the focus order and will have event listeners attached, an element with &lt;code&gt;role=&amp;quot;button&amp;quot;&lt;/code&gt; will &lt;em&gt;not&lt;/em&gt; have those characteristics by default.&lt;br /&gt;
Please read &lt;a href=&quot;https://html5accessibility.com/stuff/2024/07/15/what-aria-still-does-not-do/&quot;&gt;What ARIA still does not do&lt;/a&gt; for details.&lt;br /&gt;
A popular use case for ARIA is custom elements, to appreciate what you need to do to make them accessible, the &lt;a href=&quot;https://www.tpgi.com/web-components-punch-list/&quot;&gt;Web Components punch list&lt;/a&gt; may be helpful.&lt;/p&gt;
&lt;h2 id=&quot;last-words&quot;&gt;Last words&lt;/h2&gt;
&lt;p&gt;We &lt;cite&gt;&lt;a href=&quot;https://webaim.org/projects/million/#aria&quot;&gt;already know&lt;/a&gt;&lt;/cite&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Increased ARIA usage on pages was associated with higher detected errors. The more ARIA attributes that were present, the more detected accessibility errors could be expected.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do not introduce more ARIA into your code in an effort to please the knowledge ghouls of OpenAI and their &lt;a href=&quot;https://html5accessibility.com/stuff/2025/10/23/atlas-ableism/&quot;&gt;new browser&lt;/a&gt;. Although you wouldn&#39;t know it from the &lt;a href=&quot;https://adrianroselli.com/2025/10/openai-aria-and-seo-making-the-web-worse.html&quot;&gt;&lt;em&gt;bumpf&lt;/em&gt; OpenAI published&lt;/a&gt; - &lt;strong&gt;It is not needed&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;and a merry fucking xmas to all!&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Discover Dialog</title>
    <link href="https://htmhell.dev/adventcalendar/2025/9/"/>
    <updated>2025-12-09T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/9/</id>
    <content type="html">by Sara Joy&lt;br&gt;&lt;p&gt;Suffering modal woes? Positioning, backdrops, focus trapping, z-index — Oof.&lt;/p&gt;
&lt;p&gt;Just as I was, some of you may have been coding a lot of these functions into a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; by hand with CSS and JavaScript, or using a library to handle them for you.&lt;/p&gt;
&lt;p&gt;Either way, things are getting simpler and more declarative all the time - and when we&#39;re so busy working, we don&#39;t always realise how much has changed! Maybe this will help you shave off some lines of code or remove some dependencies from your codebase.&lt;/p&gt;
&lt;p&gt;To those of you new to building on the web, this is for you too, as you lucky things get to skip the old ways :)&lt;/p&gt;
&lt;h2 id=&quot;meet-lessdialoggreater&quot;&gt;Meet &lt;button id=&quot;openMeetDialog&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/button&gt;&lt;/h2&gt;
&lt;dialog id=&quot;meetDialog&quot; closedby=&quot;any&quot;&gt;
  &lt;p&gt;
    Hello 👋
    &lt;br /&gt;Nice to meet you!
  &lt;/p&gt;
  &lt;form method=&quot;dialog&quot;&gt;
    &lt;button&gt;Close&lt;/button&gt;
  &lt;/form&gt;
&lt;/dialog&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog&quot;&gt;dialog element&lt;/a&gt; has been available across browsers since March 2022, and allows you to pop a little overlay on your page - a common variant is known as a modal - and it has a whole bunch of abilities built in, with further useful facets still being added.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dialog&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;meetDialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    Hello 👋&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;br&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;Nice to meet you!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Close&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;modal-and-non-modal&quot;&gt;Modal and non-modal&lt;/h2&gt;
&lt;p&gt;We&#39;re probably more familiar with the modal variety of dialog, intended to (hopefully only briefly) stop you interacting with the page under it. But there are also plenty of non-modal dialogs to be seen around the web, for example &lt;button id=&quot;openToastDialog&quot;&gt;toast&lt;/button&gt; notifications.&lt;/p&gt;
&lt;dialog id=&quot;toastDialog&quot; closedby=&quot;any&quot; style=&quot;
    margin: 0;
    border-width: 0.25em 1em 1em 0.25em;
    border-style: solid;
    border-radius: 1.5em 2em 0.5em 1em;
    border-color: saddlebrown;
    background-color: burlywood;
    box-shadow: 1em 1em 1.5em -0.5em #8888;
    rotate: 10deg;
    position: fixed;
    left: 3em;
    bottom: 3em;
    z-index: 10;
  &quot;&gt;
  &lt;p&gt;
    Pop! Do I look
    &lt;br /&gt; a little burned?
  &lt;/p&gt;
  &lt;form method=&quot;dialog&quot;&gt;
    &lt;button&gt;Close&lt;/button&gt;
  &lt;/form&gt;
&lt;/dialog&gt;
&lt;p&gt;The &lt;code&gt;dialog&lt;/code&gt; element gives us both modal and non-modal variants, depending on how we open them. In the case of more than one dialog being opened (assuming no close action happening on the previous dialogs), the most recently opened dialog will appear on top.&lt;/p&gt;
&lt;h2 id=&quot;opening-with-js&quot;&gt;Opening with JS&lt;/h2&gt;
&lt;p&gt;To open a dialog, we use one of two JavaScript functions on a dialog element:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showModal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Likely based on the click of a button, you will run something like the following (you will likely use a much more specific &lt;code&gt;querySelector&lt;/code&gt;):&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dialog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// or&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dialog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showModal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;highlight&quot;&gt;💡
  There is a declarative method available to &lt;a href=&quot;https://htmhell.dev/adventcalendar/2025/7/&quot;&gt;invoke&lt;/a&gt; dialogs, but for now I will stick to what is currently available across the main browsers.
&lt;/p&gt;
&lt;p&gt;In the CodePen below, both kinds of dialog opening method are available. You&#39;ll notice that you can still interact with the Open Modal button after having opened the dialog, but not vice-versa. The modal can be closed with the Esc key, the non-modal dialog cannot.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;300&quot; data-default-tab=&quot;js,result&quot; data-slug-hash=&quot;ZYQvJQG&quot; data-pen-title=&quot;Dialogs!&quot; data-editable=&quot;true&quot; data-user=&quot;sarajw&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
      &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/sarajw/pen/ZYQvJQG&quot;&gt;
  Dialogs!&lt;/a&gt; by Sara (&lt;a href=&quot;https://codepen.io/sarajw&quot;&gt;@sarajw&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
      &lt;/p&gt;
      &lt;script async=&quot;&quot; src=&quot;https://public.codepenassets.com/embed/index.js&quot;&gt;&lt;/script&gt;
&lt;h2 id=&quot;closing-dialogs&quot;&gt;Closing dialogs&lt;/h2&gt;
&lt;p&gt;You&#39;ll also not see any JS for the closure of the dialogs. Pop into the HTML tab in the demo, and you might spot the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/form#method&quot;&gt;&lt;code&gt;method=&amp;quot;dialog&amp;quot;&lt;/code&gt;&lt;/a&gt; in the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element wrapping the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;. Here I&#39;m only using it to close the dialogs with said button. If you include more inputs here, &lt;code&gt;method=&amp;quot;dialog&amp;quot;&lt;/code&gt; will send a submit event and close the dialog, but not actually submit any data anywhere.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Close&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dialogs can also be closed without using this form method, instead by activating some JS (maybe also with a button):&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dialog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// or&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dialog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;requestClose&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/requestClose&quot;&gt;&lt;code&gt;requestClose()&lt;/code&gt;&lt;/a&gt; is a newly available addition, allowing access to the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/cancel_event&quot;&gt;cancel event&lt;/a&gt;, otherwise thrown before the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/close_event&quot;&gt;close event&lt;/a&gt; when exiting a modal with the &lt;code&gt;Esc&lt;/code&gt; key. This may be useful to create &lt;em&gt;&amp;quot;are you sure?&amp;quot;&lt;/em&gt; type interactions. (Please do so with care if you must! We&#39;ll have no deceptive patterns here..)&lt;/p&gt;
&lt;h3 id=&quot;light-dismissal&quot;&gt;Light dismissal&lt;/h3&gt;
&lt;p&gt;You&#39;re probably already trying to close the dialogs by clicking outside of them, which is a common pattern and is often referred to as &lt;a href=&quot;https://html.spec.whatwg.org/dev/interactive-elements.html#dialog-light-dismiss&quot;&gt;&lt;em&gt;light dismiss&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This isn&#39;t available by default, but can be coded in with CSS and JS.&lt;/p&gt;
&lt;p&gt;With thanks to &lt;a href=&quot;https://gomakethings.com/revisiting-how-to-dismiss-native-html-dialog-elements-when-the-backdrop-is-clicked/&quot;&gt;Chris Ferdinandi&lt;/a&gt; and &lt;a href=&quot;https://bsky.app/profile/konnorrogers.com/post/3lxczan6dh22b&quot;&gt;Konnor Rogers&lt;/a&gt; for the inspiration, I find the following code works well for &lt;strong&gt;modal&lt;/strong&gt; dialogs only, through the magic of the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/::backdrop&quot;&gt;&lt;code&gt;::backdrop&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* disallow pointer events on the backdrop, so they&lt;br /&gt;   don&#39;t register as clicks on the dialog itself */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;dialog::backdrop&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;pointer-events&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;click&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// find any open modal dialogs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; openDialogs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dialog[open]:modal&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// return if none open&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;openDialogs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;// check for clicks on documentElement, passed through the backdrop&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;documentElement&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;// close the open dialogs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    openDialogs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;dialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; dialog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;300&quot; data-default-tab=&quot;js,result&quot; data-slug-hash=&quot;yyepzaX&quot; data-pen-title=&quot;Dialogs with light dismiss (JS)&quot; data-editable=&quot;true&quot; data-user=&quot;sarajw&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
      &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/sarajw/pen/yyepzaX&quot;&gt;
  Dialogs with light dismiss (JS)&lt;/a&gt; by Sara (&lt;a href=&quot;https://codepen.io/sarajw&quot;&gt;@sarajw&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
      &lt;/p&gt;
      &lt;script async=&quot;&quot; src=&quot;https://public.codepenassets.com/embed/index.js&quot;&gt;&lt;/script&gt;
&lt;p class=&quot;highlight&quot;&gt;💡
  You may have spotted we selected &lt;code&gt;dialog[open]&lt;/code&gt; in the JS above.
  &lt;br /&gt;
  &lt;br /&gt;Yes, open dialogs do get &lt;code&gt;open&lt;/code&gt; added as an attribute, and it is &lt;em&gt;possible&lt;/em&gt; to toggle this to open and close a dialog, but it is &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/open&quot;&gt;not recommended&lt;/a&gt;. It will always open as a non-modal dialog when done in this way, and may lead to confused or missing &lt;code&gt;close&lt;/code&gt; events.
&lt;/p&gt;
&lt;p&gt;I am selecting &lt;code&gt;:modal&lt;/code&gt; dialogs only in the code and demonstration above - but you can omit this if you want the click-away to also close any &lt;em&gt;non&lt;/em&gt;-modal dialogs that happen to be open at the same time.&lt;/p&gt;
&lt;p&gt;To achieve light dismiss on non-modal dialogs alone is trickier unfortunately, as they have no backdrop to play with...&lt;/p&gt;
&lt;p&gt;But there is some light at the end of the dismiss tunnel with the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/closedBy&quot;&gt;&lt;code&gt;closedby&lt;/code&gt;&lt;/a&gt; property, which is very nearly available across the big browsers - so please feel free to poke any friendly Safari developers you might know! Then it could look as simple as the below:&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;300&quot; data-default-tab=&quot;html,result&quot; data-slug-hash=&quot;myVNLmb&quot; data-pen-title=&quot;Dialogs with light dismiss (closedby)&quot; data-editable=&quot;true&quot; data-user=&quot;sarajw&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
    &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/sarajw/pen/myVNLmb&quot;&gt;
Dialogs with light dismiss (closedby)&lt;/a&gt; by Sara (&lt;a href=&quot;https://codepen.io/sarajw&quot;&gt;@sarajw&lt;/a&gt;)
on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
    &lt;/p&gt;
    &lt;script async=&quot;&quot; src=&quot;https://public.codepenassets.com/embed/index.js&quot;&gt;&lt;/script&gt;
&lt;h2 id=&quot;(some)-styling-built-in&quot;&gt;(Some) styling built in&lt;/h2&gt;
&lt;p&gt;Apart from limiting the piratey &lt;em&gt;lorem ipsum&lt;/em&gt; column width and centering it, no other custom styling has occurred in the CodePen demos.&lt;/p&gt;
&lt;p&gt;By default, the non-modal dialog has no backdrop, while the modal dialog&#39;s &lt;code&gt;::backdrop&lt;/code&gt; has a subtle transparent grey, and the dialog itself is centered vertically as well as horizontally on the page.&lt;/p&gt;
&lt;p&gt;I am going to stand on the shoulders of giants here, and suggest some places you can go to look at amazing dialog CSS styling and animation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nerdy.dev/have-a-dialog&quot;&gt;Have a dialog by Adam Argyle at nerdy.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tricks.com/getting-creative-with-html-dialog/&quot;&gt;Getting Creative With HTML Dialog by Andy Clarke at css-tricks.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://frontendmasters.com/blog/animating-dialog/&quot;&gt;Animating the Dialog Element by Matthew Morete at frontendmasters.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;scrollin-scrollin-scrollin&quot;&gt;Scrollin&#39;, scrollin&#39;, scrollin&#39;...&lt;/h2&gt;
&lt;p&gt;That by default the website under your modal is still scrollable may or may not bother you. It bothers &lt;em&gt;me&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;There are ways and means to stop that happening, thankfully.&lt;/p&gt;
&lt;p&gt;A classic and elegant way made possible with the sort-of-new-but-well-supported &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:has&quot;&gt;&lt;code&gt;:has()&lt;/code&gt;&lt;/a&gt; pseudo-class and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/scrollbar-gutter&quot;&gt;&lt;code&gt;scrollbar-gutter&lt;/code&gt;&lt;/a&gt; property is the following:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* Check whether any modal dialogs are open */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;html:has(dialog[open]:modal)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;/* Poof! No more scrolling! */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;/* keep the scrollbar width */&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;scrollbar-gutter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stable&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;scrollbar-gutter&lt;/code&gt; property keeps the text on the page from reflowing with a jerk, when it suddenly becomes one scrollbar-width wider as the rest of the page beyond the viewport is hidden.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;💡
  If you have both non-modal and modal dialogs on your page, be sure to use &lt;code&gt;:modal&lt;/code&gt; in your selector so this only triggers on open &lt;em&gt;modal&lt;/em&gt; dialogs.
&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;300&quot; data-default-tab=&quot;css,result&quot; data-slug-hash=&quot;OPMzjBY&quot; data-pen-title=&quot;Modal dialog with scroll-stop&quot; data-editable=&quot;true&quot; data-user=&quot;sarajw&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
      &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/sarajw/pen/OPMzjBY&quot;&gt;
  Modal dialog with scroll-stop&lt;/a&gt; by Sara (&lt;a href=&quot;https://codepen.io/sarajw&quot;&gt;@sarajw&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
      &lt;/p&gt;
      &lt;script async=&quot;&quot; src=&quot;https://public.codepenassets.com/embed/index.js&quot;&gt;&lt;/script&gt;
&lt;p&gt;You may have noticed - if you can see a scrollbar - that the scrollbar gutter isn&#39;t taking on the backdrop style. Yeah. Go ahead and comment out the &lt;code&gt;scrollbar-gutter: stable;&lt;/code&gt; line in the CSS, open/close the modal a few times, and see whether the scrollbar appearing and disappearing bothers you more. It might not - but it bothers &lt;em&gt;me&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;Reinstate &lt;code&gt;scrollbar-gutter: stable;&lt;/code&gt;, then scroll down a little in the CSS of the above CodePen and uncomment the following:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;dialog[open]::backdrop&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; transparent&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token property&quot;&gt;backdrop-filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;blur&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;0.25rem&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here I&#39;ve dropped the default shading of the &lt;code&gt;::backdrop&lt;/code&gt; and applied a blur instead - meaning the gutter blends in, assuming the gutter and page are both the same colour. You might even have some fun seeing how the scrollbars change with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/color-scheme&quot;&gt;&lt;code&gt;color-scheme&lt;/code&gt;&lt;/a&gt;...&lt;/p&gt;
&lt;p&gt;Honestly though, different browsers and OSes and dark and light modes and device types make scroll bars look different all over the place.&lt;/p&gt;
&lt;p&gt;On a MacBook whether you even &lt;em&gt;see&lt;/em&gt; the scrollbar when you&#39;re not actively scrolling depends on whether you have an external pointing device connected or not! So many people now browse the web with mobile devices, where the scrollbars and gutters are largely hidden - so it likely isn&#39;t worth spending too much effort trying to &amp;quot;fix&amp;quot; this. Trust me. Don&#39;t waste your time on it, I&#39;ve wasted enough for both of us!&lt;/p&gt;
&lt;h2 id=&quot;accessibility&quot;&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;As it opens, by default the focus will land on either the whole dialog, or if it has one, the first focusable element (whether it&#39;s a close button or not). A sighted user with a pointing device will probably not tend to notice where the focus lands - but it&#39;s very important as a screen reader user, as the focus determines where in a document the reader lands and begins reading from.&lt;/p&gt;
&lt;p&gt;In case of needing the focus to land somewhere specific for your use case, I heartily recommend reading &lt;a href=&quot;https://adrianroselli.com/2025/06/where-to-put-focus-when-opening-a-modal-dialog.html?Theme=Light&quot;&gt;Where to Put Focus When Opening a Modal Dialog&lt;/a&gt; by Adrian Roselli to help you decide where the focus will land on your dialog. Then read &lt;a href=&quot;https://www.matuzo.at/blog/2023/focus-dialog/&quot;&gt;O dialog focus, where art thou?&lt;/a&gt; to help you consistently get it where you want it.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;
  If you read the MDN page on dialogs and are bothered by &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#attributes&quot;&gt;this warning about &lt;code&gt;tabindex&lt;/code&gt; on &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;&lt;/a&gt;, you may either take Adrian or Manuel&#39;s word that it&#39;s OK, or you can enjoy Manuel&#39;s deep dive into &lt;a href=&quot;https://www.matuzo.at/blog/2025/whats-an-interactive-element&quot;&gt;What&#39;s an interactive element?&lt;/a&gt;. Enjoy!
&lt;/p&gt;
&lt;h2 id=&quot;dialogs-discovered&quot;&gt;Dialogs discovered&lt;/h2&gt;
&lt;p&gt;I hope this has been enough to convince you that it&#39;s worth using dialogs, if you aren&#39;t already, or maybe you&#39;ve found a couple of interesting tidbits you otherwise weren&#39;t aware of.&lt;/p&gt;
&lt;p&gt;HTML is still changing and improving - it&#39;s not at all archaic or just there to provide &amp;lt;div&amp;gt;s into which we can inject all the things with JavaScript (though of course you can still do that, just please inject accessible elements)!&lt;/p&gt;
&lt;p&gt;Feel free to contact me on the &lt;a href=&quot;https://sarajoy.dev/#find&quot;&gt;social medias&lt;/a&gt; to start a, uh, dialog.&lt;/p&gt;
&lt;script&gt;
  const meetDialogButton = document.getElementById(&quot;openMeetDialog&quot;);
  const meetDialog = document.getElementById(&quot;meetDialog&quot;);
  meetDialogButton.addEventListener(&quot;click&quot;, () =&gt; meetDialog.showModal());
  const toastDialogButton = document.getElementById(&quot;openToastDialog&quot;);
  const toastDialog = document.getElementById(&quot;toastDialog&quot;);
  toastDialogButton.addEventListener(&quot;click&quot;, () =&gt; toastDialog.show());
&lt;/script&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>What&#39;s wrong with this HTML, and is it valid?</title>
    <link href="https://htmhell.dev/adventcalendar/2025/8/"/>
    <updated>2025-12-08T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/8/</id>
    <content type="html">by Patrick Brosset&lt;br&gt;&lt;p&gt;Behold this magnificient HTML document:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;marginheight&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;150&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;marginwidth&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;300&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;bgcolor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;black&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;white&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;marquee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Hello &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;HTML&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; World!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;marquee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To try it in your browser, copy the following line and paste it into the address bar of your browser:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;data:text/html,&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;body &lt;span class=&quot;token assign-left variable&quot;&gt;marginheight&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;150&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;marginwidth&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;bgcolor&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;black &lt;span class=&quot;token assign-left variable&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;white&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;marquee&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Hello &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;HTML&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/b&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; World&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/i&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;/marquee&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;whats-wrong-with-it?&quot;&gt;What&#39;s wrong with it?&lt;/h2&gt;
&lt;p&gt;Everything? I mean, this HTML looks like it was written in 1998!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The document is in &lt;em&gt;quirks mode&lt;/em&gt; because it lacks a proper &lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/Doctype&quot;&gt;&lt;code&gt;DOCTYPE&lt;/code&gt; preamble&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you&#39;ve never heard of quirks mode, then you&#39;re probably lucky enough to have started your web development career after it was an important thing to know about. Suffice to say it&#39;s weird. Here are some of the ways quirks mode impacts (or impacted) HTML documents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The box model used to behave differently in older browsers, which affected layout and spacing. For example, in quirks mode, Internet Explorer included the padding and borders in the element&#39;s total width and height. Today, all browsers apply width and height to the content box of an element by default, unless you change the &lt;code&gt;box-sizing&lt;/code&gt; CSS property.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/8/box-sizing-differences.png&quot; alt=&quot;A diagram showing the difference between the box model in quirks mode and standards mode.&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Font sizes don&#39;t inherit on table elements.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Certain inline elements, such as images, don&#39;t vertically align the way you think they should when they&#39;re the only element inside a block-level container.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can see a live example of some of these quirks on my site at &lt;a href=&quot;https://patrickbrosset.com/lab/quirksmode/&quot;&gt;Quirks mode vs Standards mode&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag is missing, which means the document has no &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; either, which is bad for accessibility and UX in general&lt;/p&gt;
&lt;p&gt;A common thing that assistive technology users do is read the title of a page first to know if they want to spend more time reading the page&#39;s content. Without a descriptive title, folks are forced to start reading more of the content to know if that&#39;s what they were looking for in the first place, which is time-consuming and potentially confusing.&lt;/p&gt;
&lt;p&gt;In addition, a title is also useful for SEO purposes, is displayed in browser tabs, used when bookmarking pages, and more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag uses deprecated attributes: &lt;code&gt;marginheight&lt;/code&gt;, &lt;code&gt;marginwidth&lt;/code&gt;, &lt;code&gt;bgcolor&lt;/code&gt;, and &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These attributes are &lt;a href=&quot;https://html.spec.whatwg.org/multipage/obsolete.html#obsolete&quot;&gt;obsolete and discouraged by the spec itself&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;marquee&amp;gt;&lt;/code&gt; tag is &lt;a href=&quot;https://html.spec.whatwg.org/multipage/obsolete.html#the-marquee-element&quot;&gt;obsolete&lt;/a&gt; and should be avoided in favor of CSS animations.&lt;/p&gt;
&lt;p&gt;Plus, if you really must animate scrolling text, then please use the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-motion&quot;&gt;&lt;code&gt;prefers-reduced-motion&lt;/code&gt; media query&lt;/a&gt; to respect user preferences.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; tags look like they&#39;re used for styling. That&#39;s wrong, right?&lt;/p&gt;
&lt;p&gt;More on that later.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; tags are improperly nested. The nesting is &lt;code&gt;&amp;lt;b&amp;gt;&amp;lt;i&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;/i&amp;gt;&lt;/code&gt; which is out of order.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The closing &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;/html&amp;gt;&lt;/code&gt; tags are missing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;is-this-valid-html?&quot;&gt;Is this valid HTML?&lt;/h2&gt;
&lt;p&gt;Well, yes and no:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No: if you send this to the &lt;a href=&quot;https://validator.w3.org/nu/&quot;&gt;W3C HTML validator&lt;/a&gt;, it&#39;ll be pretty angry at you and will list the errors I mentioned earlier.&lt;/li&gt;
&lt;li&gt;But also, yes: the resulting page just loads and works fine in browsers. See for yourself:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/8/browser-rendering.png&quot; alt=&quot;A browser window showing the live webpage, which has a black background, and the phrase Hello HTML World! in white.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Before discussing each point in details, don&#39;t you think this is just beautiful? HTML is so self-correcting that making a browser fail only by using HTML is really hard to achieve, and HTML that looks like it was written two decades ago still works! I mean, take a look at &lt;a href=&quot;https://www.spacejam.com/1996/&quot;&gt;spacejam.com&lt;/a&gt;, &lt;a href=&quot;https://www.thecrystalcornerbar.com/&quot;&gt;this old bar website&lt;/a&gt;, or even &lt;a href=&quot;https://info.cern.ch/hypertext/WWW/TheProject.html&quot;&gt;the very first web page that was ever created&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now let&#39;s go over the list of issues I mentioned earlier one more time, but this time, let&#39;s talk about why they&#39;re not actually causing any problems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Sure, quirks mode can lead to weird rendering issues if you don&#39;t know that you&#39;re using it, but it&#39;s still implemented in browsers and perfectly ok to use.&lt;/p&gt;
&lt;p&gt;Even if quirks mode was added for &lt;a href=&quot;https://quirks.spec.whatwg.org/#history&quot;&gt;historical reasons&lt;/a&gt;, to support web pages that were made before the CSS specification was fully fleshed out, the code in browser engines, which detects the document mode and renders it accordingly, is here to stay.&lt;/p&gt;
&lt;p&gt;There really is no reason for browsers to ever remove it, unless one day, all quirks mode documents were to disappear from the web. This seems highly unlikely though. Judging by Chrome&#39;s &lt;a href=&quot;https://chromestatus.com/metrics/feature/timeline/popularity/2034&quot;&gt;QuirksModeDocument usage metric&lt;/a&gt;, about 30% of all page loaded in Chrome still use quirks mode! A bunch of the sites that are listed on that usage metric page appear to be using it from iframes created to display ads. Still, that&#39;s a lot of page loads.&lt;/p&gt;
&lt;p&gt;If you&#39;re encountering weird rendering issues that you can&#39;t explain, double check that you have a &lt;code&gt;DOCTYPE&lt;/code&gt; in your HTML document. You can also run the following line of code in the browser console: &lt;code&gt;document.compatMode&lt;/code&gt;. If it returns &lt;code&gt;BackCompat&lt;/code&gt;, then you&#39;re in quirks mode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag can definitely be omitted. Neither the &lt;a href=&quot;https://html.spec.whatwg.org/multipage/semantics.html#the-head-element&quot;&gt;HTML specification&lt;/a&gt;, nor browser implementations require the tag to be present.&lt;/p&gt;
&lt;p&gt;It&#39;s bad for accessibility reasons if you omit it, again because you probably also won&#39;t have a &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; tag, but it still works.&lt;/p&gt;
&lt;p&gt;In fact, you can also omit &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tags too. Personally, I commonly use this to quickly test things out in the browser. Instead of creating a new HTML file on my computer, which takes a bit more time, I just type some HTML in the address bar directly. For example: &lt;code&gt;data:text/html,&amp;lt;div&amp;gt;something&lt;/code&gt;. No &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;, no &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;, no &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; elements.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;marginheight&lt;/code&gt;, &lt;code&gt;marginwidth&lt;/code&gt;, &lt;code&gt;bgcolor&lt;/code&gt;, or &lt;code&gt;text&lt;/code&gt; are deprecated &lt;em&gt;presentational attributes&lt;/em&gt;. But, even if they&#39;re deprecated and discouraged, they&#39;re still implemented in browsers, for backward compatibility reasons.&lt;/p&gt;
&lt;p&gt;In fact, here are other similar attributes: &lt;code&gt;bgColor&lt;/code&gt;, &lt;code&gt;fgColor&lt;/code&gt;, &lt;code&gt;linkColor&lt;/code&gt;, &lt;code&gt;alinkColor&lt;/code&gt;, and &lt;code&gt;vlinkColor&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you&#39;re as old as I am, you might have used these attributes a long time ago, perhaps when creating sites in FrontPage or Dreamweaver.&lt;/p&gt;
&lt;p&gt;Anyway, these presentational attributes act as 0-specificity CSS properties, which means that any CSS property you set in a stylesheet will override them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;marquee&amp;gt;&lt;/code&gt; element still animates text in browsers. In fact, if you want to go crazy with it, try nesting two &lt;code&gt;&amp;lt;marquee&amp;gt;&lt;/code&gt; elements, like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;marquee&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   &lt;span class=&quot;token attr-name&quot;&gt;direction&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;down&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   &lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;200&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;200&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token attr-name&quot;&gt;behavior&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;   &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;marquee&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;behavior&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This text will bounce&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;marquee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;marquee&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Take a look at &lt;a href=&quot;https://codepen.io/captainbrosset/pen/dPGvrMQ?editors=1100&quot;&gt;the example on codepen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For an accessible alternative, see Daniela Kubesch&#39;s article &lt;a href=&quot;https://www.htmhell.dev/adventcalendar/2022/15/&quot;&gt;Get that marquee ✨AeStHeTiC✨&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; is perfectly valid. They used to be meant for making the text bold and italic, hence their names. But they were deprecated in HTML4, and the meaning of the tags was changed to mean something else. The &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; tag now means &lt;em&gt;bring attention&lt;/em&gt; and the &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; tag now means &lt;em&gt;idiomatic text&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; is now used to mark up keywords, product names, or other spans of text whose typical presentation would be boldfaced, but not including any special importance.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt; is now used to mark up text that is set off from the normal prose for readability reasons.&lt;/p&gt;
&lt;p&gt;More semantic tag names have since been invented too: &lt;code&gt;&amp;lt;strong&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;em&amp;gt;&lt;/code&gt;, or &lt;code&gt;&amp;lt;mark&amp;gt;&lt;/code&gt;, which convey slightly different semantics.&lt;/p&gt;
&lt;p&gt;If there&#39;s no semantic aspect to the piece of text you want to make bold or italic, don&#39;t use &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;i&amp;gt;&lt;/code&gt;, use CSS &lt;code&gt;font-weight&lt;/code&gt; and &lt;code&gt;font-style&lt;/code&gt; instead.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Misnested tags can sometimes happen in HTML, and when it does, the page doesn&#39;t break!&lt;/p&gt;
&lt;p&gt;That&#39;s the beauty of HTML once again. If you&#39;re coming from an XML background, you might be surprised by the forgiveness of HTML. But, in the vast majority of cases, HTML parsers just figure things out on their own and get you what you want.&lt;/p&gt;
&lt;p&gt;In our example, the markup is &lt;code&gt;&amp;lt;b&amp;gt;&amp;lt;i&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;/i&amp;gt;&lt;/code&gt;, which feels obviously wrong because the closing &lt;code&gt;&amp;lt;/b&amp;gt;&lt;/code&gt; tag should appear after the closing &lt;code&gt;&amp;lt;/i&amp;gt;&lt;/code&gt; tag, to respect nesting. This particular markup creates the following DOM tree:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/8/misnested-tags-dom.png&quot; alt=&quot;A diagram representation of the resulting DOM tree. The first  node contains the text node Hello, following by a nested  node, which contains the text node HTML. The  node is then followed by a sibling  node which contains a text node World!&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This behavior is actually specified in the HTML spec, and called the &lt;em&gt;adoption agency algorithm&lt;/em&gt;. I think we owe it to &lt;a href=&quot;https://cwilso.com/&quot;&gt;Chris Wilson&lt;/a&gt; for thinking about this in the first place. Chris, if you ever find traces of old discussions about this, or care to write the backstory, I would be very interested!&lt;/p&gt;
&lt;p&gt;Of course, I&#39;m not saying you should do this. It&#39;s still important to create correctly nested HTML markup. But there are historical reasons for things like this to work. Back in the early days, browser engines didn&#39;t always agree on how to parse and render HTML. So, in order to ensure that as much of the web as possible was supported across all browsers, it was sometimes easier to just support how other browsers did things. And that&#39;s how things like misnested tags ended up being supported.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Missing end tags are fine. The HTML parser is able to close most of them on its own.&lt;/p&gt;
&lt;p&gt;For example, a list item doesn&#39;t need to be closed if what follows is another list item or the end of the list. So, this works fine:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Item 1&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Item 2&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Item 3&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same is true for paragraphs. You can omit the closing &lt;code&gt;&amp;lt;/p&amp;gt;&lt;/code&gt; tag if what follows is another paragraph, a heading, a list, and a whole lot of other elements:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This is a paragraph&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This is another paragraph&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This is a heading&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This is yet another paragraph&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;section&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can find out more about these examples, and others, in the &lt;a href=&quot;https://html.spec.whatwg.org/multipage/syntax.html#optional-tags&quot;&gt;Optional tags section of the HTML spec&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, think about it, you&#39;re probably already using this without realizing it. Have you ever closed a &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, or &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag? Probably not, and that&#39;s fine. The HTML spec defines a whole lot of elements which don&#39;t require closing tags: &lt;code&gt;&amp;lt;base&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;hr&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, and others.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/xhtml1/&quot;&gt;XHTML&lt;/a&gt; attempted to change this by requiring all tags to be closed, and conforming to XML syntax rules, but that never really caught on. Sure, HTML is weird, but it&#39;s also what powers billions of web pages today. There isn&#39;t really a reason to try and change te nature of HTML.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;so-whats-the-moral-of-the-story?&quot;&gt;So, what&#39;s the moral of the story?&lt;/h2&gt;
&lt;p&gt;HTML can be very forgiving, and browsers implement things that may seem obscure or weird, but they do so for a very good reason: backward compatibility!&lt;/p&gt;
&lt;p&gt;The web is the only platform where sites that were written years ago can still work fine today. This isn&#39;t to say that things never get removed though, they do, and probably more often than you realize. Remember AppCache, WebSQL, module import assertions, or special rules that apply to the font-size of &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; elements when nested inside certain elements?&lt;/p&gt;
&lt;p&gt;This is both a blessing and a curse. The fact that so much of the languages we use are so forgiving and time-enduring made the web what it is today: a welcoming platform that doesn&#39;t take so much effort to get used to, and kind of just works. But, this also means that old features and bad practices can linger on for a long time and, if they&#39;re used by many sites and users, can&#39;t really ever be removed.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Controlling dialogs and popovers with the Invoker Commands API</title>
    <link href="https://htmhell.dev/adventcalendar/2025/7/"/>
    <updated>2025-12-07T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/7/</id>
    <content type="html">by Aubrey Sambor&lt;br&gt;&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Invoker_Commands_API&quot;&gt;Invoker Commands API&lt;/a&gt; adds new attributes to the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element to control interactive elements on the page such as popovers and modal dialogs without having to write JavaScript. Dialogs have been available in all modern browsers since March 2022, and the Popover API is available in all modern browsers as of January 2025.&lt;/p&gt;
&lt;p&gt;Until now, users wanting to implement the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element needed to write their own JavaScript to power the show and hide functionality using the &lt;code&gt;HTMLDialogElement&lt;/code&gt; interface, while the Popover API and Invoker Commands API for popovers work identically by using &lt;code&gt;HTMLElement&lt;/code&gt; attributes to show, hide, or toggle the popover.&lt;/p&gt;
&lt;p&gt;Why should you use this new API, and what benefits does it bring?&lt;/p&gt;
&lt;h2 id=&quot;dialogs-vs-popovers&quot;&gt;Dialogs vs Popovers&lt;/h2&gt;
&lt;p&gt;First, let&#39;s go over the difference between a dialog and a popover. Hidde de Vries &lt;a href=&quot;https://hidde.blog/dialog-modal-popover-differences/&quot;&gt;wrote a blog post in 2022&lt;/a&gt; detailing the differences, but in short:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dialogs usually contain an action to take, such as agreeing to text or choosing an option. Popovers usually display short-lived information such as a date picker or toast notification.&lt;/li&gt;
&lt;li&gt;By default, dialog must be explicitly closed, either by taking an action within the dialog or closing via a close button. A popover can be lightly dismissed by clicking outside of the popover.&lt;/li&gt;
&lt;li&gt;A dialog can either be modal or non-modal, while a popover is always non-modal by design. As of late 2025 the Invoker Commands API only has a built-in command for a modal dialog, so I will be focusing on modal dialogs only in this post.&lt;/li&gt;
&lt;li&gt;Dialogs have a built in backdrop functionality to tint the background a different color, while popovers shouldn&#39;t use a backdrop in most cases.&lt;/li&gt;
&lt;li&gt;A dialog is an HTML element with a role of &lt;code&gt;dialog&lt;/code&gt;, while a popover is considered an attribute and needs a role to be added depending on the popover&#39;s context. See &lt;a href=&quot;https://hidde.blog/popover-semantics/&quot;&gt;Hidde de Vrie&#39;s post on popover semantics&lt;/a&gt; to learn more about potential roles to add to your popover!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-command-and-commandfor-attributes&quot;&gt;The &lt;code&gt;command&lt;/code&gt; and &lt;code&gt;commandfor&lt;/code&gt; attributes&lt;/h2&gt;
&lt;p&gt;The Invoker Commands API introduces two new attributes to the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element—&lt;code&gt;command&lt;/code&gt; and &lt;code&gt;commandfor&lt;/code&gt;.  The &lt;code&gt;commandfor&lt;/code&gt; attribute acts as a connector between the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; controlling the functionality and the element that the command acts upon, while &lt;code&gt;command&lt;/code&gt; contains the action that should be taken on the element.&lt;/p&gt;
&lt;p&gt;As of late 2025 the following commands are supported within the API, which right now can only be used for &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;div role=&amp;quot;dialog&amp;quot;&amp;gt;&lt;/code&gt; elements or on elements with the &lt;code&gt;popover&lt;/code&gt; attribute. These commands are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;show-modal&lt;/code&gt;: Shows a &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element as a modal. If you&#39;re familiar with the underlying API to show a &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; as a modal, this is equivalent to the &lt;code&gt;HTMLDialogElement.showModal()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;close&lt;/code&gt;: Closes a &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element. This is equivalent to the &lt;code&gt;HTMLDialogElement.close()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;request-close&lt;/code&gt;: This command works similarly to the &lt;code&gt;close&lt;/code&gt; command, but before the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; can be closed, a &lt;code&gt;cancel&lt;/code&gt; event is triggered first to cancel the closure of the dialog if required actions do not occur, such as selecting required options within the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;. This is equivalent to the &lt;code&gt;HTMLDialogElement.requestClose()&lt;/code&gt; method. This concept is a little tricky, so I&#39;ll show an example later in the post.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;show-popover&lt;/code&gt;: Shows a popover element. This is equivalent to both the &lt;code&gt;popoveraction=&amp;quot;show&amp;quot;&lt;/code&gt; attribute and the &lt;code&gt;HTMLElement.showPopover()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hide-popover&lt;/code&gt;: Hides a popover element. This is equivalent to both the &lt;code&gt;popoveraction=&amp;quot;hide&amp;quot;&lt;/code&gt; attribute and the &lt;code&gt;HTMLElement.hidePopover()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;toggle-popover&lt;/code&gt;: Toggles a popover element; if the popover is hidden, it will be shown, and if the popover is shown, it will be hidden. This is equivalent to both the &lt;code&gt;popoveraction=&amp;quot;toggle&amp;quot;&lt;/code&gt; attribute and the &lt;code&gt;HTMLElement.togglePopover()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;Custom values: This is where The Invoker API really shines! A user can provide a custom value, prefixed by two hyphens (&lt;code&gt;--&lt;/code&gt;) to create a custom &lt;code&gt;command&lt;/code&gt; event. This event is usually written in JavaScript and provided by the user to add new functionality. The possibilities are endless!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;
&lt;h3 id=&quot;the-invoker-commands-api-with-a-lessdialoggreater-element&quot;&gt;The Invoker Commands API with a &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element&lt;/h3&gt;
&lt;p&gt;This is a basic example of how to use the Invoker Commands API with a &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element. One button fires the &lt;code&gt;show-modal&lt;/code&gt; command when it is clicked, and within the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;, another button fires the &lt;code&gt;close&lt;/code&gt; command to close the dialog. No JavaScript necessary, it&#39;s all built in for you!&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;commandfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;show-modal&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Open dialog&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dialog&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Dialog content&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;commandfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Close dialog&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;the-request-close-command-on-a-lessdialoggreater-element&quot;&gt;The &lt;code&gt;request-close&lt;/code&gt; command on a &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element&lt;/h3&gt;
&lt;p&gt;To use the &lt;code&gt;request-close&lt;/code&gt; command, a bit of JavaScript is needed. First, use the same code as above, but change the command on the button inside the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; from &lt;code&gt;close&lt;/code&gt; to &lt;code&gt;request-close&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;commandfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;show-modal&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Open dialog&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dialog&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Dialog content&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;commandfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;request-close&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Close dialog&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, since a &lt;code&gt;cancel&lt;/code&gt; event is fired on the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element (as that&#39;s the element that can be closed), an event listener needs to be added to capture the cancel event when &lt;code&gt;request-close&lt;/code&gt; is called. In this example, an alert displays when the close button is clicked, and then, when the user clicks &#39;OK&#39;, the alert closes and then the dialog closes. This causes the user to have to perform an action before the dialog is closed.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; myFancyDialog &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;my-fancy-dialog&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;myFancyDialog&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cancel&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;A cancel event gets fired when using the &#39;request-close&#39; command.&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;the-invoker-commands-api-with-the-popover-attribute&quot;&gt;The Invoker Commands API with the popover attribute&lt;/h3&gt;
&lt;p&gt;Commands for the popover attribute also exist in the Invoker Commands API. The new &lt;code&gt;show-popover&lt;/code&gt;, &lt;code&gt;hide-popover&lt;/code&gt;, and &lt;code&gt;toggle-popover&lt;/code&gt; commands are equivalent to the &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;hide&lt;/code&gt;, and &lt;code&gt;toggle&lt;/code&gt; values on the &lt;code&gt;popovertargetaction&lt;/code&gt; attribute in the Popover API. The &lt;code&gt;popover&lt;/code&gt; attribute still needs to be added to the popover&#39;s container, but the Invoker Commands API handles the rest of the popover&#39;s functionality.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;commandfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mycommandpopover&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;toggle-popover&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Toggle popover&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mycommandpopover&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popover&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Popover content&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;the-invoker-commands-api-with-a-custom-command&quot;&gt;The Invoker Commands API with a custom command&lt;/h3&gt;
&lt;p&gt;This is where the Invoker Commands API gets fun! You can add your own custom commands if the command you wish to run does not exist. Since a mechanism for opening and closing &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; elements does not yet exist as a command, I wrote a custom &lt;code&gt;--toggle-details&lt;/code&gt; command to open and close the &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element when the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element is clicked.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-button&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;commandfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-details&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;--toggle-details&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Open details element&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;details&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-fancy-details&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This is a details element&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Here is the text inside the details element, opened by a custom command!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; detailsElement &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;detailsElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;command &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;--toggle-details&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    detailsElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;open &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;detailsElement&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;open&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking ahead&lt;/h2&gt;
&lt;p&gt;The Invoker Commands API is not widely supported across all modern browsers just yet—as of late 2025, the Invoker Commands API is available in Chrome and Edge as of version 135, Opera as of version 120, Firefox as of version 144, and Safari Technology Preview. However, if older browsers need to be supported, you&#39;re in luck as there&#39;s a &lt;a href=&quot;https://github.com/keithamus/invokers-polyfill&quot;&gt;polyfill&lt;/a&gt; created by the API author.&lt;/p&gt;
&lt;p&gt;To learn what&#39;s coming next for the Invoker Commands API, the authors have created an &lt;a href=&quot;https://open-ui.org/components/future-invokers.explainer/&quot;&gt;explainer document&lt;/a&gt; with potential future enhancements to the API, including commands to open, close, or toggle a &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element, a command to open a native HTML date picker, and commands to play, pause, and mute HTML &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; elements. Users can also &lt;a href=&quot;https://github.com/openui/open-ui/issues&quot;&gt;submit an issue&lt;/a&gt; to add other commands that are not yet implemented—go forth and add your ideas!&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.logrocket.com/can-native-web-apis-replace-custom-components-2025/#invoker-commands&quot;&gt;Can native web APIs replace custom components in 2025?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/blog/command-and-commandfor&quot;&gt;Introducing command and commandfor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webinista.com/updates/command-and-commandfor-invoker-commands-api&quot;&gt;&lt;code&gt;command&lt;/code&gt; and &lt;code&gt;commandfor&lt;/code&gt;: the Invoker Commands API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gomakethings.com/going-javascript-free-with-the-new-invoker-command-api/&quot;&gt;Going JavaScript-free with the new Invoker Command API!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Accessible by Design: The Role of the &#39;lang&#39; Attribute</title>
    <link href="https://htmhell.dev/adventcalendar/2025/6/"/>
    <updated>2025-12-06T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/6/</id>
    <content type="html">by Todd Libby&lt;br&gt;&lt;p&gt;When starting a project, whether it is an application, a mobile app or site, or just a website in general I still see an alarming number of examples where the language attribute is not included in the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element. Not the &lt;code&gt;!DOCTYPE&lt;/code&gt;, but the element directly after the DOCTYPE.&lt;/p&gt;
&lt;p&gt;I have audited many sites and many frameworks in the past, I have noticed an alarming omission right from the outset when developers are building sites or applications. Especially in the mobile space and let&#39;s face it, in web development we focus on making things for ourselves and if &lt;em&gt;it works on our computer, it must work everywhere! Right?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I see it more prevalent these days. There are surveys out and the issue of accessibility education in university or boot camps still lacks. New developers entering the field who aren&#39;t aware, framework authors that just don&#39;t know, understand, or they just don&#39;make their work accessible.&lt;/p&gt;
&lt;p&gt;I am here to discuss the importance of the language attribute in your code.&lt;/p&gt;
&lt;h2 id=&quot;the-attribute-and-the-importance-of-the-language-used&quot;&gt;The Attribute and the Importance of the Language Used&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Sometimes, a tiny detail can make or break the experience for millions of users.&lt;/strong&gt; One of these tiny, powerful details is the &lt;code&gt;lang&lt;/code&gt; attribute in your HTML.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;lang&lt;/code&gt; attribute is a simple piece of code that tells &lt;em&gt;web browsers and screen readers&lt;/em&gt; what human language your page is written in. For example:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;html lang=&amp;quot;en&amp;quot;&amp;gt;&lt;/code&gt; means the page is in English.&lt;br /&gt;
&lt;code&gt;&amp;lt;html lang=&amp;quot;es&amp;quot;&amp;gt;&lt;/code&gt; means the page is in Spanish.&lt;/p&gt;
&lt;p&gt;When you forget this attribute, you&#39;re not just missing a semantic tag—you&#39;re creating a &lt;strong&gt;major accessibility barrier&lt;/strong&gt;. If you don&#39;t tell the computer what language you&#39;re using, assistive tools won&#39;t know how to read your content correctly.&lt;/p&gt;
&lt;h2 id=&quot;there-is-data-here-and-you-should-read-it&quot;&gt;There Is Data Here and You Should Read It&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://webaim.org/projects/million/&quot;&gt;WebAIM Million Report&lt;/a&gt; is an accessibility report done by WebAIM every year and it&#39;s an accessibility evaluation of the top one million homepages on the internet. 2025 marked the seventh year this has been done and the results are not surprising.&lt;/p&gt;
&lt;h3 id=&quot;lets-show-the-data-for-the-language-attribute&quot;&gt;Let&#39;s show the data for the language attribute.&lt;/h3&gt;
&lt;img src=&quot;https://res.cloudinary.com/colabottles/image/upload/v1760556179/images/webaim-million-2.png&quot; alt=&quot;A graph showing the top six accessibility issues found in the top one million websites by WebAIM. Low contrast of text is number one followed by missing alt text, missing labels, empty links, empty buttons and finally missing language attribute.&quot; width=&quot;702&quot; height=&quot;262&quot; loading=&quot;lazy&quot; /&gt;
&lt;p&gt;For the seventh year in a row, a missing document language made the list.&lt;/p&gt;
&lt;img src=&quot;https://res.cloudinary.com/colabottles/image/upload/v1760556179/images/webaim-million-3.png&quot; alt=&quot;A graph showing the top six accessibility issues found in the top one million websites by WebAIM by year starting in 2019 up to 2025. Low contrast of text is number one followed by missing alt text, missing labels, empty links, empty buttons and finally missing language attribute.&quot; width=&quot;702&quot; height=&quot;297&quot; loading=&quot;lazy&quot; /&gt;
&lt;p&gt;As with the rest of the items in the data, it has been a common theme the last seven years. Missing language attribute has always been the last item on the &lt;em&gt;repeating list of common failures&lt;/em&gt;. So what are the implications?&lt;/p&gt;
&lt;p&gt;A numerical look shows the data is still trending to the &lt;strong&gt;same six problems&lt;/strong&gt; in the report. So why is it that these issues are the ones that stay in the top six?&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://res.cloudinary.com/colabottles/image/upload/v1760556179/images/webaim-million-1.png&quot; alt=&quot;The WebAIM Million report showing the percentage of top million websites tested and the percentage of those with issues.&quot; width=&quot;702&quot; height=&quot;276&quot; loading=&quot;lazy&quot; /&gt;
&lt;figcaption&gt;The WebAIM Million Report showing low contrast of text at 79.1% followed by missing alternative text for images at 55.5%, missing form input labels at 48.2%, empty links at 45.4%, empty buttons at 29.6%, and finally missing language attribute at 15.8%.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;what-happens-when-the-language-is-missing?-the-wrong-voice-problem&quot;&gt;What Happens When the Language is Missing? The Wrong Voice Problem&lt;/h2&gt;
&lt;p&gt;The main group affected by a missing &lt;code&gt;lang&lt;/code&gt; tag is the screen reader user. Screen readers are essential tools that read web content aloud. They&#39;re mainly used by people who are blind, have low vision or for those that use text-to-speech. They are also used by people that find reading difficult for other reasons, this is a common practice with people with ADHD (Adult attention-Deficit/Hyperactivity Disorder).&lt;/p&gt;
&lt;p&gt;Screen readers don&#39;t just use one voice; they use specialized software packages for each language. This software knows the pronunciation rules, rhythm, and stress for English, French, Japanese, etc.&lt;/p&gt;
&lt;p&gt;When your page is missing the &lt;code&gt;lang&lt;/code&gt; attribute, the screen reader has to guess the language. It usually guesses based on the user&#39;s computer settings (for example, if the user lives in Germany, the screen reader will try to use the German voice).&lt;/p&gt;
&lt;h3 id=&quot;example-english-text-read-by-a-german-voice&quot;&gt;Example: English Text Read by a German Voice&lt;/h3&gt;
&lt;p&gt;Imagine your entire website is in clear English. If a German screen reader tries to read it, it will apply German pronunciation rules.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;&amp;ldquo;The&amp;rdquo; might sound like &amp;ldquo;Tee-hay.&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;or;&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;&amp;ldquo;Data&amp;rdquo; might be pronounced with a hard &amp;lsquo;A&amp;rsquo; sound instead of a soft one.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The result is garbled, unnatural, and often unintelligible speech. The text is still on the page, but for the screen reader user, the content is lost. They cannot understand your article, buy your product, or use your service.&lt;/p&gt;
&lt;p&gt;This single small mistake transforms your helpful website into a frustrating, unusable experience.&lt;/p&gt;
&lt;h2 id=&quot;its-a-rule-not-a-suggestion-(wcag)&quot;&gt;It&#39;s a Rule, Not a Suggestion (WCAG)&lt;/h2&gt;
&lt;p&gt;Using the &lt;code&gt;lang&lt;/code&gt; attribute isn&#39;t just a friendly suggestion; it&#39;s a &lt;strong&gt;core requirement&lt;/strong&gt; for making your website accessible.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;&lt;a href=&quot;https://www.w3.org/TR/WCAG22/&quot; title=&quot;The Web Content Accessibility Guidelines&quot;&gt;Web Content Accessibility Guidelines (WCAG)&lt;/a&gt;&lt;/em&gt; are the international standard for web accessibility. WCAG &lt;strong&gt;&lt;a href=&quot;https://www.w3.org/WAI/WCAG22/Understanding/language-of-page.html&quot; title=&quot;Success Criteria 3.1.1 - Language of Page&quot;&gt;Success Criterion 3.1.1 (Language of Page)&lt;/a&gt;&lt;/strong&gt; states that the language of the page must be clear to the computer. This is a level ‘A’ requirement, which means it&#39;s mandatory for basic accessibility.&lt;/p&gt;
&lt;p&gt;If your website fails this check, it is officially considered inaccessible.&lt;/p&gt;
&lt;h2 id=&quot;how-it-affects-other-tools&quot;&gt;How It Affects Other Tools&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;lang&lt;/code&gt; attribute helps more than just screen readers:&lt;/p&gt;
&lt;h3 id=&quot;1-braille-displays&quot;&gt;1. Braille Displays&lt;/h3&gt;
&lt;p&gt;A refreshable braille display translates text into small patterns of raised bumps. Different languages use different contraction rules in braille (called Grade 2 braille). If the language is not set, the braille translator might use the wrong rules, turning clear text into meaningless gibberish for the braille reader.&lt;/p&gt;
&lt;h3 id=&quot;2-automated-translation&quot;&gt;2. Automated Translation&lt;/h3&gt;
&lt;p&gt;When a user relies on tools like Google Translate or a browser&#39;s built-in translation feature, telling the tool the source language (the language you wrote it in) ensures a much more accurate translation. If the source language is unclear, the translation quality drops sharply. &lt;a href=&quot;https://www.matuzo.at/blog/lang-attribute/&quot;&gt;An example can be found here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;3-quotation-marks&quot;&gt;3. Quotation Marks&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;lang&lt;/code&gt; attribute helps the browser and other user agents select the correct typographical glyphs for quotation marks, especially when it comes to when the &lt;code&gt;&amp;lt;q&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;blockquote&amp;gt;&lt;/code&gt; elements are used (when styled using CSS generated content such as &lt;code&gt;content: open-quote&lt;/code&gt;). For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In English &lt;code&gt;lang=&amp;quot;en&amp;quot;&lt;/code&gt;, quotes are typically “double quotes”.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In German &lt;code&gt;lang=&amp;quot;de&amp;quot;&lt;/code&gt;, they are often rendered as „low-9 quotes‟.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In French &lt;code&gt;lang=&amp;quot;fr&amp;quot;&lt;/code&gt;, they use « guillemets ».&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While less related to &lt;em&gt;visual&lt;/em&gt; quotation marks, providing the correct language helps assistive technologies &lt;strong&gt;pronounce&lt;/strong&gt; the surrounding text accurately, ensuring a fluid and comprehensible reading experience.&lt;/p&gt;
&lt;p&gt;Not providing the correct language may cause browsers to default to the user&#39;s system language or a neutral setting for quotation marks  which may not match the document&#39;s language which results in incorrect or confusing typography (e.g., using English quote marks for German language).&lt;/p&gt;
&lt;p&gt;Without a declared language, a screen reader may attempt to read the text using incorrect phonetic rules, voice, and accent. Which makes the content sound like gibberish and can make it incomprehensible for users who rely on audio output.&lt;/p&gt;
&lt;h3 id=&quot;4-hyphenation&quot;&gt;4. Hyphenation&lt;/h3&gt;
&lt;p&gt;Proper hyphenation is entirely language-dependent. Hyphenation rules can be complex and unique to each language. when CSS is used, &lt;code&gt;hyphens: auto&lt;/code&gt;, the browser or user agent relies on the &lt;code&gt;lang&lt;/code&gt; attribute to load the appropriate hyphenation dictionary and apply correct linguistic rules which can improve text flow and readability. Especially in justified or narrow columns.&lt;/p&gt;
&lt;p&gt;For example, a long compound word in German, &lt;code&gt;lang=&amp;quot;de&amp;quot;&lt;/code&gt;, will be broken according to German rules such as &lt;strong&gt;Rechtsschutzversicherungsgesellschaften&lt;/strong&gt; (which means, insurance companies providing legal protection).&lt;/p&gt;
&lt;p&gt;Most browsers do not provide automatic hyphenation if the language is not declared. This can not only lead to unsightly text blocks with excessive white space between words, but also horizontal scrolling or overflow on mobile devices which severely impacts readability and layout stability.&lt;/p&gt;
&lt;p&gt;If the browser attempts to guess the language or uses the wrong default, it could apply the incorrect hyphenation rules, which breaks words in places that are linguistically wrong, which, in turn, confuses the reader.&lt;/p&gt;
&lt;h2 id=&quot;what-about-pages-with-two-languages?&quot;&gt;What About Pages with Two Languages?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;What if your page is mostly English but includes a quote in Spanish?&lt;/em&gt; If you don&#39;t do anything, the screen reader will read the Spanish quote using the English voice, again leading to mispronunciation.&lt;/p&gt;
&lt;p&gt;You can fix this instantly by adding the &lt;code&gt;lang&lt;/code&gt; attribute to the specific element that changes language:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    The artist once said, &quot;Always remember this phrase:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;fr&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Je ne regrette rien.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&quot; I think that sums up his career.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this code, the screen reader switches to the French voice for the quote and then immediately switches back to the English voice for the rest of the sentence. This small change ensures all users hear the content exactly as intended.&lt;/p&gt;
&lt;h2 id=&quot;how-to-set-the-language-in-modern-web-frameworks&quot;&gt;How to Set the Language in Modern Web Frameworks&lt;/h2&gt;
&lt;p&gt;In modern websites built with tools like React, Vue, or Angular, you usually don&#39;t touch the main HTML file very often. Since these tools mostly control the content inside the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tag, you have to know where to find the root template file to set the &lt;code&gt;lang&lt;/code&gt; attribute correctly. for example,&lt;/p&gt;
&lt;p&gt;React uses the file, &lt;code&gt;public/index.html&lt;/code&gt;. Therefore you would directly place the attribute in the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag in that file.&lt;/p&gt;
&lt;h3 id=&quot;heres-a-simple-guide-for-the-most-popular-frameworks&quot;&gt;Here&#39;s a simple guide for the most popular frameworks:&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:left&quot;&gt;Framework&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;What File to Edit&lt;/th&gt;
&lt;th style=&quot;text-align:right&quot;&gt;Where to Put the Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;React&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;public/index.html&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;Directly on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag in that file.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Next.js&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;app/layout.tsx (or similar root file)&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;Set the lang in the JSX for the root &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Vue&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;public/index.html&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;Directly on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag in that file.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Nuxt&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;nuxt.config.ts&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;Inside the app.head.htmlAttrs setting in your config file.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Angular&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;src/index.html&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;Directly on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag in that file.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:left&quot;&gt;Svelte/SvelteKit&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;index.html or src/app.html&lt;/td&gt;
&lt;td style=&quot;text-align:right&quot;&gt;Directly on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag in the main template file.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;example-setting-the-language-in-a-static-template&quot;&gt;Example: Setting the Language in a Static Template&lt;/h3&gt;
&lt;p&gt;For most simple apps (React, Angular, plain HTML), you will open your main &lt;code&gt;index.html&lt;/code&gt; file and change the first line like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Change the line below from &amp;lt;html&gt; to the correct language code --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;en&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- ... --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Your app code loads here --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;lang&lt;/code&gt; attribute is a tiny line of code that provides &lt;strong&gt;universal access to your content&lt;/strong&gt;. It&#39;s arguably the easiest, fastest, and most impactful accessibility fix you can make on any website.&lt;/p&gt;
&lt;p&gt;By correctly setting the language, you ensure that everyone has equal access to your content. Regardless of whether they use a screen reader, braille display, or translation tool to do so, their tools have the fundamental information they need to do their jobs correctly. It&#39;s a simple commitment that makes the web better for everyone.&lt;/p&gt;
&lt;p&gt;Don&#39;t let a missing two-letter code turn your content into a foreign language for your users and don&#39;t be afraid to use it or add it in!&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>IDREFs: What they are and how to use them</title>
    <link href="https://htmhell.dev/adventcalendar/2025/5/"/>
    <updated>2025-12-05T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/5/</id>
    <content type="html">by Kilian Valkhof&lt;br&gt;&lt;p&gt;Take the following HTML for example:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Email address&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; element is associated with the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element because the input is nested inside of the label, and the browser now knows to offer additional behavior: when the user clicks on the label, the input will be focused. That&#39;s not behavior that you had to specify with an onclick handler, the browser just infers it from the relationship between the elements.&lt;/p&gt;
&lt;p&gt;But what if it can&#39;t infer the relationship? While your Firefox, Chrome or &lt;a href=&quot;https://polypane.app/&quot;&gt;Polypane browser&lt;/a&gt; can all figure this out, some assistive technologies can&#39;t. Both Dragon Naturally Speaking and VoiceOver on macOS have trouble associating labels with inputs when they are nested, according to &lt;a href=&quot;https://a11ysupport.io/tests/html_label_element_implicit&quot;&gt;a11ysupport tests&lt;/a&gt;. So while clicking the label will focus the input, giving the voice command &amp;quot;Focus Email address&amp;quot; might not work. That said, support might have improved since the tests were last conducted: My editor Zoë tested this in Safari 26.0.1 on macOS 15.7.1 where it now works. Make sure to test before relying on this behavior!&lt;/p&gt;
&lt;p&gt;Additionally, this association only works when the input is nested inside the label. If you wanted to have the label and input be siblings, for example for styling purposes, then that implicit association is lost.&lt;/p&gt;
&lt;p&gt;To solve this, we can use the &lt;code&gt;IDREF&lt;/code&gt; you probably already know, the &lt;code&gt;for&lt;/code&gt; attribute on the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; element:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; Email address &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we&#39;re &lt;em&gt;explicitly&lt;/em&gt; associating the label with the input, by referencing the input&#39;s &lt;code&gt;id&lt;/code&gt; from the label&#39;s &lt;code&gt;for&lt;/code&gt; attribute. That&#39;s all an &lt;code&gt;IDREF&lt;/code&gt; really is: a reference to another element&#39;s &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note, there&#39;s also nothing keeping you from using the &lt;code&gt;for&lt;/code&gt; attribute and nesting both at the same time:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Email address&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you know what an &lt;code&gt;IDREF&lt;/code&gt; is! In HTML there are many other places where you can use &lt;code&gt;IDREF&lt;/code&gt;s to create explicit relationships between elements, many of which are ARIA attributes that help with accessibility and with describing more complex relationships than HTML can express. We&#39;ll get to those in a bit, because there&#39;s more to be said about &lt;code&gt;IDREF&lt;/code&gt;s themselves.&lt;/p&gt;
&lt;h2 id=&quot;ids-need-to-be-unique&quot;&gt;IDs need to be unique&lt;/h2&gt;
&lt;p&gt;In a well-structured HTML document, each &lt;code&gt;id&lt;/code&gt; is only used once. This is important for &lt;code&gt;IDREF&lt;/code&gt;s to work properly, since the browser or assistive technology needs to be able to find the single right element when following an &lt;code&gt;IDREF&lt;/code&gt;. If there are multiple elements with the same &lt;code&gt;id&lt;/code&gt;, this can lead to unexpected behavior.&lt;/p&gt;
&lt;p&gt;Making sure IDs are unique can be tricky: you might have multiple forms on a page that reuse the same naming, or another repeated structure that requires ARIA attributes. When that happens, consider a programmatic way to generate unique IDs, for example by prefixing them with the component name.&lt;/p&gt;
&lt;h2 id=&quot;ids-need-to-exist&quot;&gt;IDs need to exist&lt;/h2&gt;
&lt;p&gt;This might seem obvious, but the majority of issues that occur around &lt;code&gt;IDREF&lt;/code&gt;s is that the referenced ID simply doesn&#39;t exist in the document. This can happen when you make a typo in the &lt;code&gt;id&lt;/code&gt; or &lt;code&gt;IDREF&lt;/code&gt;, or when you remove an element but forget to update the references to it.&lt;/p&gt;
&lt;p&gt;Linters and validators can help catch these issues, as can browser developer tools that highlight broken references. In Polypane, for example, broken &lt;code&gt;IDREF&lt;/code&gt;s are &lt;a href=&quot;https://polypane.app/docs/elements-panel/#idrefs&quot;&gt;highlighted in the Element panel&lt;/a&gt;, making it easy to spot and fix them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/images/advent2025/idrefs/idrefs.png&quot; alt=&quot;Polypane&#39;s Element panel highlighting a broken for attribute&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In other browsers you can check for missing IDs using this little console snippet that gathers all &lt;code&gt;for&lt;/code&gt; attributes on labels and checks if the referenced ID exists:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[for]&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; label&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;for&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Label with for=&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot; has no matching element with that ID.&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      label&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;other-html-idref-attributes&quot;&gt;Other HTML IDREF attributes&lt;/h2&gt;
&lt;p&gt;HTML has quite a few attributes that use &lt;code&gt;IDREF&lt;/code&gt;s to create relationships between elements, including some &lt;em&gt;very&lt;/em&gt; new ones.&lt;/p&gt;
&lt;h3 id=&quot;the-for-attribute-on-lesslabelgreater-elements&quot;&gt;The &lt;code&gt;for&lt;/code&gt; attribute on &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; elements&lt;/h3&gt;
&lt;p&gt;As we&#39;ve seen above.&lt;/p&gt;
&lt;p&gt;A neat trick that &lt;code&gt;for&lt;/code&gt; has: you can link as many labels as you want to a single input:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; Email address &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; required &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These will all focus the same input, and their combinined text will be used as the accessible name for the input: &lt;code&gt;Email address required&lt;/code&gt;. Of course, that&#39;s the &lt;em&gt;theory&lt;/em&gt;. In practice, support for inputs with multiple labels is inconsistent. Some assistive technologies will use all labels but some only use the first or the last one (see &lt;a href=&quot;https://github.com/dequelabs/axe-core/issues/689#issuecomment-490176712&quot;&gt; this research&lt;/a&gt; done by Deque). So while it&#39;s valid HTML, you&#39;re better off sticking to a single label per input for now.&lt;/p&gt;
&lt;h3 id=&quot;the-form-attribute-on-form-associated-elements&quot;&gt;The &lt;code&gt;form&lt;/code&gt; attribute on form-associated elements&lt;/h3&gt;
&lt;p&gt;You can add a &lt;code&gt;form&lt;/code&gt; attribute to form-associated elements like &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; to associate them with a specific &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element on your page, even if they are not nested inside that form:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;signup-form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;signup-form&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Sign up&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Something to keep in mind is that the &lt;code&gt;form&lt;/code&gt; atttribute &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/form#non-inheritance_of_the_form_attribute&quot;&gt;only works for the current element&lt;/a&gt;, not its children. If you have a &lt;code&gt;&amp;lt;fieldset&amp;gt;&lt;/code&gt; with a &lt;code&gt;form&lt;/code&gt; attribute, the inputs inside it will not be associated with the form unless they also have a &lt;code&gt;form&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;Another thing to keep in mind is that you can remove an element from a form by giving it a &lt;code&gt;form&lt;/code&gt; attribute that points to a different form, or to no form at all (by giving it an empty string). Here&#39;s &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/form#associating_with_a_non-ancestor_form&quot;&gt;an example from MDN&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;externalForm&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;internalForm&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Username:&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;externalForm&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even though the label will focus that input, the input will be submitted with &lt;code&gt;externalForm&lt;/code&gt; and not for &lt;code&gt;internalForm&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Like the advice for labels, keeping form-associated elements inside their forms is generally easier to manage. The above might be useful design-wise when you have a wizard across multiple steps that each have their own form, but you want a submit button that&#39;s always visible across the steps.&lt;/p&gt;
&lt;h3 id=&quot;the-list-attribute-on-lessinputgreater-elements&quot;&gt;The &lt;code&gt;list&lt;/code&gt; attribute on &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; elements&lt;/h3&gt;
&lt;p&gt;If you have an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element, you can use the &lt;code&gt;list&lt;/code&gt; attribute to associate it with a &lt;code&gt;&amp;lt;datalist&amp;gt;&lt;/code&gt; element that contains predefined options for that input to have it show a dropdown and autocomplete with those options:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browsers&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browser-choice&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browser-choice&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;datalist&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;browsers&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Chrome&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Firefox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Safari&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Polypane&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;datalist&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works on desktop browsers, but you should not depend on it: mobile browsers often don&#39;t show the datalist options at all, and assistive technologies may not announce them either. So while it&#39;s a nice enhancement, make sure your form works well without it too.&lt;/p&gt;
&lt;h3 id=&quot;the-headers-attribute-on-lesstdgreater-and-lessthgreater-elements&quot;&gt;The &lt;code&gt;headers&lt;/code&gt; attribute on &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;th&amp;gt;&lt;/code&gt; elements&lt;/h3&gt;
&lt;p&gt;When you have complex tables where header cells might have subheaders, you can use the &lt;code&gt;headers&lt;/code&gt; attribute on data cells (&lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt;) and header cells (&lt;code&gt;&amp;lt;th&amp;gt;&lt;/code&gt;) to explicitly associate them with the relevant header cells:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;table&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;colspan&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Name&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;th&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;First&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;th&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;last&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Last&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;th&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;first name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Kilian&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;last name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Valkhof&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;td&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;tr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;table&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here we also introduce the concept of multiple &lt;code&gt;IDREF&lt;/code&gt;s in a single attribute. Some &lt;code&gt;IDREF&lt;/code&gt; attributes can reference &lt;em&gt;multiple&lt;/em&gt; IDs by separating them with spaces. In this case, the first data cell is associated with both the &amp;quot;First&amp;quot; and &amp;quot;Name&amp;quot; headers. When browsers now announce the cell, they can include the text of both headers in the announcement.&lt;/p&gt;
&lt;h3 id=&quot;new-html-idref-attributes-popovertarget-commandfor-anchor-and-interestfor&quot;&gt;New HTML &lt;code&gt;IDREF&lt;/code&gt; attributes: &lt;code&gt;popovertarget&lt;/code&gt;, &lt;code&gt;commandfor&lt;/code&gt;, &lt;code&gt;anchor&lt;/code&gt; and &lt;code&gt;interestfor&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;HTML is in the process of getting several new functionalities that make it easier to create declarative interactive components like popups and tooltips. To help with those, new &lt;code&gt;IDREF&lt;/code&gt; attributes are being added.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;popovertarget&lt;/code&gt; can be added to a button to associate it with a popup element that has the &lt;code&gt;popover&lt;/code&gt; attribute. That way the popover is shown when the button is activated. For a more in-depth explanation, check out &lt;a href=&quot;https://www.htmhell.dev/adventcalendar/2024/22/&quot;&gt;PSA: Stop using the title attribute as tooltip!&lt;/a&gt; from last year&#39;s advent calendar.&lt;/p&gt;
&lt;p&gt;The default action for &lt;code&gt;popovertarget&lt;/code&gt; is to toggle the popover when the button is activated, but you can use the &lt;code&gt;popovertargetaction&lt;/code&gt; attribute to change that behavior. The default value is &lt;code&gt;toggle&lt;/code&gt;, but you can also set it to &lt;code&gt;show&lt;/code&gt; or &lt;code&gt;hide&lt;/code&gt; to always show or hide the popover when the button is activated.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popovertarget&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-popover&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popovertargetaction&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;show&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Show popover&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-popover&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popover&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  This is a popover!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popovertarget&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-popover&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popovertargetaction&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;hide&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Close&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;commandfor&lt;/code&gt; does the same as popovertarget, but can also be used to open and close &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; elements declaratively with &lt;code&gt;show-modal&lt;/code&gt; and &lt;code&gt;close&lt;/code&gt; as &lt;code&gt;command&lt;/code&gt; values.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;commandfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;show-modal&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Open dialog&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dialog&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  This is a dialog!&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;commandfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;close&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Close&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lastly, &lt;code&gt;interestfor&lt;/code&gt; is similar to &lt;code&gt;commandfor&lt;/code&gt;, but is used when a user &amp;quot;expresses interest&amp;quot; in an element, for example by hovering over it or focusing it. The use case here is to show tooltips or hint popovers when the user hovers or focuses an element.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;interestfor&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-tooltip&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;I&#39;m a button!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;my-tooltip&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;popover&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;hint&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;The button does nothing.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For more on &lt;code&gt;interestfor&lt;/code&gt;, check out the OpenUI explainer on &lt;a href=&quot;https://open-ui.org/components/interest-invokers.explainer/&quot;&gt;interest invokers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;popovertarget&lt;/code&gt; works in all browsers, while &lt;code&gt;commandfor&lt;/code&gt; is still lacking support in Safari. &lt;code&gt;interestfor&lt;/code&gt; is still very new and only supported in Chromium 142 and newer.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To learn more about these, keep an eye on upcoming articles in this advent calendar!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Lastly, the &lt;code&gt;anchor&lt;/code&gt; attribute will let you declaratively specify which element a popover or tooltip should be anchored to. Currently this is something you have to specify with CSS, but it can be much easier to reference an ID instead. Unfortunately &lt;a href=&quot;https://caniuse.com/mdn-html_global_attributes_anchor&quot;&gt;it&#39;s not supported yet&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;aria-idref-attributes&quot;&gt;ARIA IDREF attributes&lt;/h2&gt;
&lt;p&gt;All of which brings us to ARIA. ARIA is a set of attributes designed to add semantics, relationships and behaviors to HTML where the native elements and attributes fall short. They&#39;re not the first thing you should reach for, but there are many things where HTML alone can&#39;t express what you need.&lt;/p&gt;
&lt;p&gt;Many ARIA attributes are &lt;code&gt;IDREF&lt;/code&gt; attributes that allow you to create explicit relationships between elements.&lt;/p&gt;
&lt;h3 id=&quot;descriptive-relationships&quot;&gt;Descriptive relationships&lt;/h3&gt;
&lt;p&gt;A common use case for ARIA is to make sure that elements have an accessible name and/or description. Often you&#39;ll see this done with &lt;code&gt;aria-label&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-label&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Move to trash&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-hidden&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;🗑&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works, but aria-label comes with some downsides. For example, it&#39;s easy to miss: a common issue accessibility auditors find is that a button&#39;s HTML is copied for another purpose, but the original aria-label is not updated to reflect the new purpose. Browsers also have issues with automatic translations of aria-labels, since they are not part of the visible text on the page.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-label&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Move to trash&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- oops! --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-hidden&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;🔃 Revert&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is often better to use &lt;code&gt;aria-labelledby&lt;/code&gt; to give an element its accessible name. &lt;code&gt;aria-labelledby&lt;/code&gt; gives elements an accessible name by referencing other elements that contain the relevant text. Indeed, &lt;code&gt;aria-labelledby&lt;/code&gt; can reference multiple IDs, allowing you to combine text from different elements into a single accessible name:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;photo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;trash-label photo-label&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-hidden&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;🗑&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;trash-label&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;visually-hidden&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Delete&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;photo-label&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;IMG_0512.jpg&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;IMG_0512.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;alt&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Sydney Opera House at sunset&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above button&#39;s accessible name will be &amp;quot;Delete IMG_0512.jpg&amp;quot;, combining the text from both referenced elements and making it clear that the button deletes, and which photo it deletes.&lt;/p&gt;
&lt;p&gt;Sometimes elements might have an accessible name, but you still want to have an additional description to give more info. Visually that is easy to do, think of the word &amp;quot;required&amp;quot; below an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element. That association is not always clear to assistive technologies. To make that association explicit, you can use &lt;code&gt;aria-describedby&lt;/code&gt; and reference IDs of elements that contains the description.&lt;/p&gt;
&lt;p&gt;Again, &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-describedby&quot;&gt;MDN&lt;/a&gt; gives us a nice example:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-describedby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;trash-desc&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Move to trash&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;trash-desc&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  Items in the trash will be permanently removed after 30 days.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The button&#39;s accessible name &amp;quot;Move to trash&amp;quot; is understandable on its own, but the description provides additional context about what happens when you move something to the trash.&lt;/p&gt;
&lt;h3 id=&quot;complex-relationships&quot;&gt;Complex relationships&lt;/h3&gt;
&lt;p&gt;ARIA also has many attributes that help express more complex relationships between elements: &lt;code&gt;aria-controls&lt;/code&gt;, &lt;code&gt;aria-owns&lt;/code&gt;, &lt;code&gt;aria-activedescendant&lt;/code&gt; and &lt;code&gt;aria-flowto&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;aria-controls&lt;/code&gt; is used to indicate that an element controls another element, for example a button that shows or hides a section of content. This can help assistive technologies understand the relationship between the button and the content it controls:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-controls&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submenu&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-expaned&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;false&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Open menu&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;nav&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submenu&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;hidden&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;...&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;nav&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, the button is indicating that it controls the visibility of the &lt;code&gt;nav&lt;/code&gt; element with the ID &lt;code&gt;submenu&lt;/code&gt;. You can then combine this with &lt;code&gt;aria-expanded&lt;/code&gt; on the button to indicate whether the submenu is currently visible or hidden.&lt;/p&gt;
&lt;p&gt;To account for even more complex structures, &lt;code&gt;aria-controls&lt;/code&gt; can also reference multiple IDs, allowing a single control to manage several elements at once.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;aria-activedescendant&lt;/code&gt; is used to indicate which element within a &lt;em&gt;composite widget&lt;/em&gt; is currently active. An example of a composite widget is a combobox: a UI component that combines a text input with a list of options: You can type in the text input to filter the options, fill in freeform content or use the arrow keys to navigate the options. For a reference implementation look at the &lt;a href=&quot;https://www.w3.org/WAI/ARIA/apg/patterns/combobox/&quot;&gt;combobox&lt;/a&gt; in the WAI-ARIA Authoring Practices. Getting a combobox right is tricky, so make sure to read that guide if you&#39;re building one!&lt;/p&gt;
&lt;p&gt;You can use &lt;code&gt;aria-activedescendant&lt;/code&gt; (in combination with &lt;code&gt;aria-controls&lt;/code&gt;) on the input to indicate which option in the listbox is currently selected:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;combobox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;aria-autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;aria-haspopup&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;listbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;aria-expanded&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;false&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;aria-controls&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;options-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;aria-activedescendant&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option-2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;options-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;listbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-label&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option-1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Option 1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option-2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Option 2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option-3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Option 3&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;aria-owns&lt;/code&gt; is used to create a parent-child relationship between elements that are not nested in the DOM. When for some reason your DOM can&#39;t be structured in a way that makes sense visually or semantically (for example, you need to use a &amp;quot;portal&amp;quot; in some Javascript frameworks),&lt;code&gt;aria-owns&lt;/code&gt; will let you &amp;quot;rewrite&amp;quot; the accessibility tree as if the elements were nested. Any elements that are inside the element are listed first, and then the elements you refernece in &lt;code&gt;aria-owns&lt;/code&gt; are added as children after that.&lt;/p&gt;
&lt;p&gt;Keep in mind that when you use &lt;code&gt;aria-owns&lt;/code&gt;, all the regular rules about HTML still apply: You can&#39;t nest an interactive element inside another interactive element, and some elements can only have specific types of children. Because of this, giving a specific example for &lt;code&gt;aria-owns&lt;/code&gt; will always feel a little contrived. I&#39;m going to try anyway.&lt;/p&gt;
&lt;p&gt;Here&#39;s how you would structure a combobox where the list of options needs to be elsewhere in the DOM, for example to break out of a container with &lt;code&gt;overflow:hidden&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;combobox-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Choose an option:&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-owns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;floating-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;combobox-input&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;combobox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;aria-autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;aria-haspopup&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;listbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;aria-expanded&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;false&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;aria-controls&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;floating-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;aria-activedescendant&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- elsewhere in the dom to avoid stacking context clipping --&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;floating-list&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;listbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-label&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;options&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option-1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Option 1&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option-2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Option 2&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option-3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Option 3&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we use both &lt;code&gt;aria-controls&lt;/code&gt; and &lt;code&gt;aria-owns&lt;/code&gt; here. &lt;code&gt;aria-controls&lt;/code&gt; indicates that the div controls the listbox, while &lt;code&gt;aria-owns&lt;/code&gt; indicates that the listbox should be a child of the div in the accessibility tree. &lt;code&gt;aria-owns&lt;/code&gt; describes a &lt;em&gt;structural&lt;/em&gt; relationship, while &lt;code&gt;aria-controls&lt;/code&gt; describes a &lt;em&gt;functional&lt;/em&gt; relationship.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;aria-owns&lt;/code&gt; on its own doesn&#39;t change the browser&#39;s default behavior, where the tab order follows the DOM structure. Assistive technologies can instead use the &lt;code&gt;aria-flowto&lt;/code&gt; relationships to offer the user a way to navigate content in the suggested order.&lt;/p&gt;
&lt;p&gt;In other words, &lt;code&gt;aria-flowto&lt;/code&gt; is used to indicate a logical reading order between elements that doesn&#39;t follow the visual ordering of elements. That can happen when they&#39;re in different places in the DOM, or when you&#39;ve changed the visual order with the &lt;code&gt;order&lt;/code&gt; CSS property, or by absolute positioning elements. Using &lt;code&gt;aria-flowto&lt;/code&gt; can help assistive technologies navigate the content in a way that makes sense.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;aria-flowto&lt;/code&gt; can also reference multiple IDs. In that case, the assistive technology can give the user a choice of which element to navigate to next.&lt;/p&gt;
&lt;p&gt;As with all things ARIA, &lt;code&gt;aria-flowto&lt;/code&gt; is a last resort: it&#39;s better to structure your HTML in a way that follows a logical reading order without needing to override it with ARIA. This is doubly true for &lt;code&gt;aria-flowto&lt;/code&gt; because &lt;a href=&quot;https://a11ysupport.io/tech/aria/aria-flowto_attribute&quot;&gt;support in browsers and assistive technologies is limited&lt;/a&gt;: only the JAWS screen reader supports it at the moment.&lt;/p&gt;
&lt;h3 id=&quot;do-you-need-aria-idrefs?&quot;&gt;Do you need ARIA IDREFs?&lt;/h3&gt;
&lt;p&gt;As you can see from the descriptions above, the ARIA attributes get increasingly more esoteric and complex. Things like &lt;code&gt;aria-labelledby&lt;/code&gt; and &lt;code&gt;aria-controls&lt;/code&gt; can be useful in many situations, but others like &lt;code&gt;aria-owns&lt;/code&gt; and &lt;code&gt;aria-flowto&lt;/code&gt; are only needed for specific use cases. When you think you need ARIA it&#39;s often better to take a step back and consider if you can achieve your goal with native HTML elements and attributes.&lt;/p&gt;
&lt;p&gt;It&#39;s also important to note that none of these ARIA attributes bring any behavior on their own: they only describe relationships. This can help assistive technologies understand the structure of your page, but you&#39;ll still have to implement the actual behavior. For example, &lt;code&gt;&amp;lt;button aria-expanded=&amp;quot;false&amp;quot; aria-controls=&amp;quot;my-menu&amp;quot;&amp;gt;&lt;/code&gt; will not automatically show and hide that menu element or move the focus into it. You have to implement the show/hide behavior and focus management. The ARIA attributes just tell the browser that this button controls that menu and whether it&#39;s expanded or not.&lt;/p&gt;
&lt;h2 id=&quot;idrefs-and-how-to-use-them&quot;&gt;IDREFs and how to use them&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;IDREF&lt;/code&gt;s let you create explicit relationships between elements in your HTML where they otherwise might not exist. Some of them give you additional behaviors, like how the &lt;code&gt;for&lt;/code&gt; attribute on a label makes clicking the label focus the input, or how the &lt;code&gt;list&lt;/code&gt; attribute on an input shows a dropdown of options from a datalist.&lt;/p&gt;
&lt;p&gt;Other &lt;code&gt;IDREF&lt;/code&gt; attributes, especially in ARIA, are used to describe relationships that help assistive technologies understand the structure and purpose of your content better. If you also want those to show certain behaviors, it&#39;s your job to implement those.&lt;/p&gt;
&lt;p&gt;Whenever you use &lt;code&gt;IDREF&lt;/code&gt;s, make sure that the referenced IDs exists, and that you test their usage with the browsers and assistive technologies your users use.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Referencing HTML elements inside Shadow DOM</title>
    <link href="https://htmhell.dev/adventcalendar/2025/4/"/>
    <updated>2025-12-04T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/4/</id>
    <content type="html">by mehm8128&lt;br&gt;&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_components&quot;&gt;Web Components&lt;/a&gt; is the web standard way for creating reusable components like React or Vue components.&lt;/p&gt;
&lt;p&gt;While Web Components have matured significantly, it still has some missing pieces to make accessible components easily using &lt;a href=&quot;https://www.matuzo.at/blog/2023/pros-and-cons-of-shadow-dom/&quot;&gt;Shadow DOM&lt;/a&gt;.&lt;br /&gt;
Today I&#39;ll introduce one of these difficulties and the proposed solution to resolve it. Part of this solution is already available in Chrome Canary.&lt;/p&gt;
&lt;h2 id=&quot;problems-with-referencing-html-elements-inside-the-shadow-dom&quot;&gt;Problems with referencing HTML elements inside the Shadow DOM&lt;/h2&gt;
&lt;p&gt;First, let&#39;s consider a case where we create a checkbox component using custom elements and &lt;a href=&quot;https://web.dev/articles/declarative-shadow-dom&quot;&gt;Declarative Shadow DOM&lt;/a&gt;.&lt;br /&gt;
In this example, we want to reference the internal &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element by referencing &lt;code&gt;id=&amp;quot;checkbox&amp;quot;&lt;/code&gt; on &lt;code&gt;&amp;lt;fancy-checkbox&amp;gt;&lt;/code&gt;. Elements inside the Shadow DOM are encapsulated, that&#39;s why we cannot reference the input field directly.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  customElements&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;define&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;fancy-checkbox&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FancyCheckbox&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTMLElement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;I agree with the terms and conditions&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;fancy-checkbox&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;template&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;shadowrootmode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;open&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;inner-checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;fancy-checkbox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem with this approach is that the &lt;code&gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt; is failing to be associated with the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Clicking the label doesn&#39;t focus on the checkbox.&lt;/li&gt;
&lt;li&gt;The checkbox doesn&#39;t have an accessible name.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is the missing piece that this article addresses. It is not easy to make Web Components fully accessible using Shadow DOM.&lt;/p&gt;
&lt;p&gt;I&#39;ll introduce the proposed solutions to address these problems.&lt;/p&gt;
&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/WICG/webcomponents/blob/gh-pages/proposals/reference-target-explainer.md&quot;&gt;The proposal&lt;/a&gt; divides the work into two phases to simplify the problems.&lt;br /&gt;
Phase 1 only deals with targeting a single element in Shadow DOM.&lt;br /&gt;
Phase 2 addresses targeting multiple elements.&lt;/p&gt;
&lt;p&gt;For the initial release, only Phase 1 will be shipped.&lt;/p&gt;
&lt;h3 id=&quot;phase-1&quot;&gt;Phase 1&lt;/h3&gt;
&lt;p&gt;Let&#39;s consider an &amp;quot;enclosing element&amp;quot; concept. An &amp;quot;enclosing element&amp;quot; wraps another element and extends it with extra features and HTML elements.&lt;br /&gt;
For example, when we create a &lt;code&gt;&amp;lt;fancy-checkbox&amp;gt;&lt;/code&gt; component using the Shadow DOM, this becomes the &amp;quot;enclosing element&amp;quot; for &lt;code&gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt;. This allows us to encapsulate and make reusable components with custom styling and additional functionality.&lt;/p&gt;
&lt;p&gt;To enable referencing the &lt;code&gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt; element inside the Shadow DOM from &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt;, Phase 1 introduces the &lt;code&gt;shadowRootReferenceTarget&lt;/code&gt; attribute. This attribute specifies which element should be referenced as the target of &lt;code&gt;&amp;lt;label for=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;I agree with the terms and conditions&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;fancy-checkbox&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;template&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;shadowrootmode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;open&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;shadowRootReferenceTarget&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;inner-checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;inner-checkbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;fancy-checkbox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, when &lt;code&gt;&amp;lt;label for=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt; tries to reference &lt;code&gt;&amp;lt;fancy-checkbox id=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt;, it automatically references &lt;code&gt;&amp;lt;input id=&amp;quot;inner-checkbox&amp;quot;&lt;/code&gt; because &lt;code&gt;shadowRootReferenceTarget&lt;/code&gt; attribute designates its mapping. Finally, the label can reference the checkbox and provide the accessible name &amp;quot;I agree with the terms and conditions&amp;quot; for it. Users can also focus on it by clicking &lt;code&gt;&amp;lt;label for=&amp;quot;checkbox&amp;quot;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This also enables the use of ARIA attributes, as shown in the following example using &lt;code&gt;aria-labelledby&lt;/code&gt;. The same applies to &lt;code&gt;popovertarget&lt;/code&gt;, &lt;code&gt;commandfor&lt;/code&gt;, and &lt;code&gt;interestfor&lt;/code&gt;.&lt;br /&gt;
What attributes are in &lt;a href=&quot;https://github.com/WICG/webcomponents/issues/1091&quot;&gt;scope is not completely decided&lt;/a&gt;. Whether &lt;code&gt;aria-owns&lt;/code&gt; should be included will be discussed and all other IDREF attributes are likely to be in scope.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;aria-labelledby&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;label&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;fancy-label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;label&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;template&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;shadowrootmode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;open&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;shadowRootReferenceTarget&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;inner-label&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;label&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;inner-label&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Type your name.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;fancy-label&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Phase 1 is available in &lt;a href=&quot;https://wpt.fyi/results/shadow-dom/reference-target/tentative?label=master&amp;amp;label=experimental&amp;amp;aligned&quot;&gt;Chrome Canary&lt;/a&gt; with the &amp;quot;Experimental Web Platform features&amp;quot; flag enabled.&lt;/p&gt;
&lt;p&gt;Mozilla set their position to &amp;quot;positive&amp;quot; in &lt;a href=&quot;https://github.com/mozilla/standards-positions/issues/1035&quot;&gt;September&lt;/a&gt;, and this feature is proposed as part of &lt;a href=&quot;https://github.com/web-platform-tests/interop/issues/1011&quot;&gt;Interop 2026&lt;/a&gt;. I hope this will become available across all major browsers.&lt;/p&gt;
&lt;p&gt;Let&#39;s take a look at Phase 2 for multiple elements reference support.&lt;/p&gt;
&lt;h3 id=&quot;phase-2&quot;&gt;Phase 2&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/WICG/webcomponents/blob/gh-pages/proposals/reference-target-explainer.md#-phase-2-referring-to-specific-elements-within-a-shadow-root&quot;&gt;Phase 2&lt;/a&gt; enables referencing multiple elements or other complicated references.&lt;br /&gt;
As one of the solution for phase 2, I introduce &lt;code&gt;shadowRootReferenceTargetMap&lt;/code&gt; attribute, but other solutions are discussed so it&#39;s unclear what solution will be adopted for complicated reference.&lt;/p&gt;
&lt;p&gt;Let&#39;s consider creating a combobox using &lt;code&gt;aria-controls&lt;/code&gt; and &lt;code&gt;aria-activedescendant&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;combobox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;aria-controls&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;animals&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token attr-name&quot;&gt;aria-activedescendant&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;animals&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;animals-listbox&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;animals&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;template&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token attr-name&quot;&gt;shadowrootmode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;open&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;shadowRootReferenceTargetMap&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;aria-controls: listbox,&lt;br /&gt;                                  aria-activedescendant: opt1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;listbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;listbox&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;opt1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Otter&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;opt2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Opossum&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;option&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;opt3&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Ocelot&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;animals-listbox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first part of the value of the &lt;code&gt;shadowRootReferenceTargetMap&lt;/code&gt; attribute, &lt;code&gt;aria-controls: listbox&lt;/code&gt;, means when &lt;code&gt;aria-controls&lt;/code&gt; references &lt;code&gt;&amp;lt;animals-listbox&amp;gt;&lt;/code&gt; with the id &lt;code&gt;animals&lt;/code&gt;, it should reference an element inside the Shadow DOM with the id &lt;code&gt;listbox&lt;/code&gt;. That&#39;s &lt;code&gt;&amp;lt;div role=&amp;quot;listbox&amp;quot; id=&amp;quot;listbox&amp;quot;&amp;gt;&lt;/code&gt; here. &lt;code&gt;aria-activedescendant: opt1&lt;/code&gt; works the same way.&lt;/p&gt;
&lt;p&gt;This provides the flexibility to reference HTML elements inside the Shadow DOM, but some concerns are under discussion.&lt;/p&gt;
&lt;p&gt;Please check out these issues if you&#39;re interested in learning more.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/WICG/webcomponents/issues/1086&quot;&gt;Reference Target Tracking Issue · Issue #1086 · WICG/webcomponents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/WICG/webcomponents/issues/1111&quot;&gt;Reference Target &amp;quot;phase 2&amp;quot;: seeking feedback and use cases · Issue #1111 · WICG/webcomponents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Reference Target for Cross-root ARIA enables us to reference HTML elements inside the Shadow DOM. This makes developing accessible Web Components easier, especially for UI component libraries and design systems. OpenUI is working on &lt;a href=&quot;https://github.com/openui/design-system&quot;&gt;The OpenUI Design System&lt;/a&gt;, and this feature will be valuable for that project.&lt;/p&gt;
&lt;p&gt;I recommend trying this feature in Chrome Canary and providing feedback to the &lt;a href=&quot;https://github.com/WICG/webcomponents&quot;&gt;Web Components CG&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Speculation rules improvements</title>
    <link href="https://htmhell.dev/adventcalendar/2025/3/"/>
    <updated>2025-12-03T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/3/</id>
    <content type="html">by Barry Pollard&lt;br&gt;&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Speculation_Rules_API&quot;&gt;Speculation Rules API&lt;/a&gt; allows you to speed up future navigations by prefetching or even prerendering URLs in advance of a user actually clicking a link. When the link is clicked, the speculation is used, and the user experiences a faster load than if no speculation was used.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://schepp.dev/&quot;&gt;Schepp&lt;/a&gt; covered &lt;a href=&quot;https://htmhell.dev/adventcalendar/2024/28/&quot;&gt;the API in last year&#39;s post&lt;/a&gt; and discussed the &lt;code&gt;eagerness&lt;/code&gt; value which allowed you to, for example, hover over a link to speculatively prerender it with the simple addition of this rule to your HTML:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;speculationrules&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;prerender&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;where&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;href_matches&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/*&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;eagerness&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;moderate&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This hover technique is a common functionality offered by libraries, plugins, and frameworks, but now this is baked right into the browser. Chromium-based browsers only for now, but it is being worked on by Safari and Firefox, and as a progressive enhancement, nothing is broken on non-supporting browsers — they just don&#39;t benefit from the performance improvement.&lt;/p&gt;
&lt;p&gt;Using mouse hover as a signal works well on desktop, but what about mobile, where &amp;quot;hover&amp;quot; is not really a thing? At least in browser terms — I&#39;m sure many of us have hovered over a link with our fingers, but as that is not detected by the browser as an event, we can&#39;t act upon it.&lt;/p&gt;
&lt;p&gt;Well, solving that is just one of many improvements the API has seen in the last year that we&#39;ll cover in this post.&lt;/p&gt;
&lt;h2 id=&quot;improved-mobile-viewport-heuristics&quot;&gt;Improved mobile viewport heuristics&lt;/h2&gt;
&lt;p&gt;Since hover does not exist, we have updated the &lt;code&gt;eagerness: moderate&lt;/code&gt; on mobile to instead look at the following heuristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Anchor links within 30% vertical distance from the previous pointer down.&lt;/li&gt;
&lt;li&gt;Anchor links at least 0.5× as big as the largest anchor in the viewport.&lt;/li&gt;
&lt;li&gt;The browser waits 500 milliseconds after the user stopped scrolling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The aim is to avoid, as much as possible, over-speculating links that users are less likely to click. For example, because they are still scrolling, or they are very small links (terms and conditions and the like!).&lt;/p&gt;
&lt;p&gt;You can see this in action in the following video where the &lt;a href=&quot;https://almanac.httparchiv.org/&quot;&gt;Web Almanac&lt;/a&gt; prerenders same-origin links with &lt;code&gt;moderate&lt;/code&gt; eagerness:&lt;/p&gt;
&lt;figure&gt;
  &lt;video controls=&quot;&quot; playsinline=&quot;&quot; muted=&quot;&quot; loop=&quot;&quot;&gt;
      &lt;source src=&quot;https://htmhell.dev/images/advent2025/speculation-rules-mobile-viewport-demo.mp4&quot; width=&quot;2420&quot; height=&quot;1320&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;&lt;p&gt;An example of scrolling down a mobile page triggering speculations.&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;script&gt;
  const mediaQuery = window.matchMedia(&#39;(prefers-reduced-motion: reduce)&#39;);
  if (!mediaQuery.matches) {
      document.querySelector(&#39;video&#39;).autoplay = true;
  }
&lt;/script&gt;
&lt;p&gt;In the video, you can see that as you scroll down the page, links are being successfully prerendered, ready for the user to browse to the page.&lt;/p&gt;
&lt;p class=&quot;highlight&quot;&gt;&lt;strong&gt;Note:&lt;/strong&gt; Speculating has a cost. To both your users and for sites with potential increased traffic and resulting infrastructure usage. Always weigh those costs against the benefit to the user. Additionally, the are risks for more complex sites for speculating. See the &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/implementing-speculation-rules&quot;&gt;Guide to implementing speculation rules for more complex sites&lt;/a&gt; for more information.&lt;/p&gt;
&lt;p&gt;To conserve memory, Chrome keeps up to two speculations in memory at a time. As the user scrolls further and new links — which are more likely to be clicked on — enter the viewport, the old prerenders are cancelled. These links can be re-speculated, for example, when the user scrolls back up, in which case they can be fetched from the HTTP cache. That way, they prerender even faster.&lt;/p&gt;
&lt;h2 id=&quot;eager-eagerness-improvements&quot;&gt;&lt;code&gt;eager&lt;/code&gt; eagerness improvements&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;eager&lt;/code&gt; value has also been changed. It now offers an option somewhere between &lt;code&gt;immediate&lt;/code&gt;, where links are speculated as soon as possible, and &lt;code&gt;moderate&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On desktop, &lt;code&gt;moderate&lt;/code&gt; rules trigger after a 10 millisecond hover. On mobile, we consider &lt;em&gt;all&lt;/em&gt; links in the viewport after the user has stopped scrolling for 100 milliseconds, rather than the more restrictive set of heuristics above.&lt;/p&gt;
&lt;p&gt;One common technique is to prefetch the HTML document with &lt;code&gt;eager&lt;/code&gt; value  as that  is often relatively cheap. Then upgrade this &lt;code&gt;prefetch&lt;/code&gt; to a full &lt;code&gt;prerender&lt;/code&gt; on &lt;code&gt;moderate&lt;/code&gt; when you have more signals that the users may click on the link, and so think it&#39;s worthwhile to speculatively start to render the page in full, as prerender has more costs including downloading subresources and using memory and CPU needed to render the page.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;speculationrules&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;prefetch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;where&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;href_matches&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/*&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;eagerness&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eager&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;prerender&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;where&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;href_matches&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/*&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;eagerness&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;moderate&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition you can also restrict the links considered for speculating using the &lt;code&gt;where&lt;/code&gt; object.&lt;/p&gt;
&lt;h2 id=&quot;further-improvements-to-the-api&quot;&gt;Further improvements to the API&lt;/h2&gt;
&lt;p&gt;I&#39;ll close out with a sneak peek into the future, as one further improvement being worked on is a middle ground between the &lt;code&gt;prefetch&lt;/code&gt; and &lt;code&gt;prerender&lt;/code&gt;. This is useful for those sites concerned with any unintended consequences with fully prerendering a page.&lt;/p&gt;
&lt;p&gt;Executing JavaScript may trigger analytics, change state, or cause other changes that should not happen until the page is actually viewed. While it is possible to &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/prerender-pages#detect-prerender-in-javascript&quot;&gt;make JavaScript prerender-aware&lt;/a&gt;, or &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/prerender-pages#hold-back-other-content&quot;&gt;holdback scripts until the page is navigated to&lt;/a&gt;, this can involve a lot of efforts, particularly for large sites with lots of dependencies managed by many teams.&lt;/p&gt;
&lt;p&gt;To help with this, a new &lt;strong&gt;Prender Until Script&lt;/strong&gt; option is currently available behind a flag in Chrome (&lt;code&gt;chrome://flags/#prerender-until-script&lt;/code&gt;). As its name suggests, it will start prerendering a page, but pause when it encounters a synchronous &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; element. Scripts with the &lt;code&gt;async&lt;/code&gt; or &lt;code&gt;defer&lt;/code&gt; attribute (or &lt;code&gt;module&lt;/code&gt; scripts which are &lt;code&gt;defer&lt;/code&gt; by default) will be downloaded but not executed until the page is navigated to.&lt;/p&gt;
&lt;p&gt;This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pages without any JavaScript can be fully prerendered.&lt;/li&gt;
&lt;li&gt;Pages with only async/deferred JavaScript can be fully prerendered, with JavaScript executed on navigation.&lt;/li&gt;
&lt;li&gt;Pages with only sync &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; JavaScript can start prerender, but pause before any &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; causes any intended consequences. They will continue to download subresources (thanks to the &lt;a href=&quot;https://web.dev/articles/preload-scanner&quot;&gt;preload scanner&lt;/a&gt;), so they still have a significant performance benefit over &lt;code&gt;prefetch&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After enabling the flag, you can use this new mode in exactly the same way as &lt;code&gt;prefetch&lt;/code&gt; and &lt;code&gt;prerender&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;speculationrules&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token string&quot;&gt;&quot;prerender_until_script&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;where&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;href_matches&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/*&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;eagerness&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;moderate&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This enhancement should be released next year. In the meantime, have a play and &lt;a href=&quot;https://bsky.app/profile/tunetheweb.com&quot;&gt;let me know&lt;/a&gt; how you get on!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The Speculation Rules API continues to improve with new options and features to help site owners deliver fast, HTML-driven websites!&lt;/p&gt;
&lt;p&gt;We&#39;ve even &lt;a href=&quot;https://github.com/matuzo/HTMHell/pull/225&quot;&gt;added speculation rules to this site&lt;/a&gt;. As a light, static, HTML-driven site, it&#39;s the perfect type of site for this API. It was already a very fast site, but the addition of this API should make it even faster, especially on slower networks.&lt;/p&gt;
&lt;p&gt;Finally, with our first signs of cross-browser adoption of the API, I&#39;d speculate (boom! boom!) 2026 will be another bumper year for the API and for users of sites that implement it.&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Using the Ancient Evils for Debugging</title>
    <link href="https://htmhell.dev/adventcalendar/2025/2/"/>
    <updated>2025-12-02T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/2/</id>
    <content type="html">by Manuel Strehl&lt;br&gt;&lt;p&gt;Deep down in the dark voids of HTML specs long gone sleeps a terrifying thing. Imagine, if you will, a DOM node so mighty, that it can change the &lt;code&gt;content-type&lt;/code&gt; of parts of the document. An HTML element that makes the parser tremble and withdraw, and that cannot be stopped even by its own end tag.&lt;/p&gt;
&lt;p&gt;The wise people of W3C try to keep the knowledge of this terror away from the mere mortals’ eyes to spare us the danger of its madness. They advise us not to use the magic tag name that is the incantation for this ancient malice.&lt;/p&gt;
&lt;p&gt;We will, of course, do exactly this today. We’ll take a deep look at the&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;element and what fun things we can use it for.&lt;/p&gt;
&lt;h2 id=&quot;a-quick-warning&quot;&gt;A Quick Warning&lt;/h2&gt;
&lt;p&gt;This being said, I’d like to point out one important thing: Do not use this element in production. The HTML living standard is &lt;a href=&quot;https://html.spec.whatwg.org/multipage/obsolete.html#plaintext&quot;&gt;quite clear about this&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Elements in the following list are entirely obsolete, and must not be used by authors: [...] &lt;code&gt;plaintext&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, what does &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; do that earned it its place on HTML’s list of deprecated elements? In a nutshell, it ends the HTML parser and instructs the browser to interpret &lt;em&gt;everything&lt;/em&gt; following as plain text.&lt;/p&gt;
&lt;p&gt;That is to be taken literally. Really everything, including any closing &lt;code&gt;&amp;lt;/plaintext&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;/html&amp;gt;&lt;/code&gt;, will be printed as if a rogue, unclosed &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; would suddenly go haywire and slurp up the rest of the page. By the way, this makes &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; the only non-empty element that has no end tag at all.&lt;/p&gt;
&lt;h2 id=&quot;what-do-we-use-this-power-for?&quot;&gt;What Do We Use this Power For?&lt;/h2&gt;
&lt;p&gt;On first sight that sounds like a really stupid superpower. On second sight, it still does. We look into how that element became part of HTML below. But now we will use it for one specific purpose: debugging server-side code.&lt;/p&gt;
&lt;p&gt;Of course, specialized debuggers like XDebug for PHP or built-in error pages in frameworks like Django take over the heavy lifting here. And even the good ol’ &lt;code&gt;print &amp;quot;&amp;lt;script&amp;gt;console.log(&#39;here!&#39;)&amp;lt;/script&amp;gt;&amp;quot;&lt;/code&gt; is often helpful. Those tools should be high up in your utility belt.&lt;/p&gt;
&lt;p&gt;But imagine this: You are deep in your code, chasing an elusive bug that affects only part of the HTML output, and you want to spot on the rendered page exactly where it shows up. The fastest way is to put a quick &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; close to the offending place, reload the page, and presto! Just scan down to where the markup starts to show through.&lt;/p&gt;
&lt;p&gt;This is especially useful to access formatted debugging output. A &lt;code&gt;var_dump()&lt;/code&gt; in PHP, for example. Or an &lt;code&gt;error.stack&lt;/code&gt; stack trace in NodeJS. Slap a &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; in front of it before writing it to the HTML output, so that the string is immediately readable:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# TODO delme!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&amp;lt;plaintext&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var_dump&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$strange_variable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/2/debug_php.png&quot; alt=&quot;A screenshot of the HTMHell website where the lower part shows a PHP variable output followed by the site’s markup instead of the rendered HTML&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If you’re working on an expressJS application, it could look like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token function&quot;&gt;some_method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;plaintext&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stack&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/2/debug_express.png&quot; alt=&quot;A screenshot of the same HTMHell website as above with the lower part showing a JS error stack followed by the site’s markup instead of the rendered HTML&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-history-behind-this-evil&quot;&gt;The History behind this Evil&lt;/h2&gt;
&lt;p&gt;How ended this seemingly fringe feature up in all mainstream browsers? It was indeed there from the very beginning of HTML as this &lt;a href=&quot;https://www.w3.org/History/19921103-hypertext/hypertext/WWW/MarkUp/Tags.html&quot;&gt;historic W3C document&lt;/a&gt; from 1992 proves:&lt;/p&gt;
&lt;blockquote class=&quot;blockquote-no-quotes&quot;&gt;
&lt;p&gt;&lt;strong&gt;Plaintext&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This tag indicates that all following text is to be taken litterally [!], up to the end of the file. Plain text is designed to be represented in the same way as example XMP text, with fixed width character and significant line breaks. Format:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;PLAINTEXT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;This tag allows the rest of a file to be read efficiently without parsing. Its presence is an optimisation. There is no closing tag.&lt;/p&gt;
&lt;p&gt;This also tells us the reason for its invention. Back at the time Sir Tim Berners-Lee’s high-end NeXT PC that he used to write the first web browser had a quarter of the power of a hand-me-down 2009 smartphone. It was important to optimize wherever you could.&lt;/p&gt;
&lt;p&gt;Given that the early WWW was meant as a place to share scientific information, having a large blob of plain text as part of your fancy new HTML page was relatively common. The possibility to end the costly HTML parser and fall back to simply printing the remainder of the file as plain text was a powerful tool.&lt;/p&gt;
&lt;figure style=&quot;margin-block-end:2.4rem&quot;&gt;
&lt;img src=&quot;https://htmhell.dev/adventcalendar/2025/2/screenshot_1992.png&quot; alt=&quot;partial screenshot of a browser window. The address bar is shown, and the content of the page looks like a window of an old desktop OS.&quot; /&gt;
&lt;figcaption&gt;Screenshot: This is a rendering of &lt;a href=&quot;https://www.w3.org/History/19921103-hypertext/hypertext/WWW/MarkUp/Connolly/structure5.html&quot;&gt;a 1992 example for the use of the &lt;code&gt;&amp;lt;plaintext&gt;&lt;/code&gt; element&lt;/a&gt; by &lt;a href=&quot;https://worldwideweb.cern.ch/&quot;&gt;an emulation of the very first web browser at CERN&lt;/a&gt;. (I had to trick it a bit, though, because the file that the emulator would try to access returned a 404 error.)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Such a feature isn’t unique to HTML, either. For example, the programming language Perl uses a &lt;a href=&quot;https://perldoc.perl.org/perldata#Special-Literals&quot;&gt;special marker&lt;/a&gt; to tell the Perl parser to stop processing the remainder of the file:&lt;/p&gt;
&lt;pre class=&quot;language-perl&quot;&gt;&lt;code class=&quot;language-perl&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;this is Perl code&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;__END__&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;this isn’t anymore&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Perl programmers use this not for performance reasons but to embed additional data into their programs.)&lt;/p&gt;
&lt;p&gt;Of course, nowadays, in the face of multi-megabyte JS payloads, this optimization has become completely unnecessary.&lt;/p&gt;
&lt;h2 id=&quot;how-safe-are-we?&quot;&gt;How Safe Are We?&lt;/h2&gt;
&lt;p&gt;But the element &lt;em&gt;is&lt;/em&gt; still looming in all browsers, so it&#39;s worth keeping a bit of a working knowledge of it at the back of our minds.&lt;/p&gt;
&lt;p&gt;To give you an example of how this feature could be mis-used, assume a comment function on a blog, where the commenter was able to smuggle in the string &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt;. As good developers we know never to trust users’ input, so we put the comment through a sanitizer. Let’s take a look at where things can go south from here.&lt;/p&gt;
&lt;p&gt;We use the test string&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;world!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to check how several sanitizer libraries react to it.&lt;/p&gt;
&lt;h3 id=&quot;there-goes-the-sanity!&quot;&gt;There Goes the Sanity!&lt;/h3&gt;
&lt;p&gt;We run each sanitizer in the most minimal configuration that produces any output. This is by design: sanitizers are security products. They should produce safe output by default.&lt;/p&gt;
&lt;p&gt;The results are quite surprising, though. (Click on a library’s name below to reveal the horrifying details.) You will notice that no two libraries (apart from the Sanitizer API and DOMPurify, where the former was directly inspired by the latter) agree on how to sanitize our test string.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;The new HTML Sanitizer API as implemented in Firefox&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Document/parseHTML_static&quot;&gt;developer.mozilla.org/en-US/docs/Web/API/Document/parseHTML_static&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseHTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The approach of this API is to somehow get the nesting correct again according to the HTML5 parser spec. That is, close the &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; tags, then re-open the &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; tag as the spec suggests. The API does not deal with the special semantics of &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; at all, though.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We end up with a string that has the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; element and its content stripped away:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Poor man’s DOM sanitizing&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; div &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;div&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;div&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;TEST_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;div&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For this test we set the test string via &lt;code&gt;HTMLElement.innerHTML = test_string&lt;/code&gt; and read it again via &lt;code&gt;.innerHTML&lt;/code&gt;. Chrome and Firefox show the same result. This does not really sanitize anything. But we include it in the list, because it demonstrates what the JS engine will do to the test string when interpreting it as HTML.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The result is a mangled version of the original, which will have double-encoded content in the still retained &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;world!&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/plaintext&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/b&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/p&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;NB:&lt;/em&gt; We can trick the Sanitizer API into producing this output, too, if we’re careless with its configuration:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;Document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parseHTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; sanitizer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; removeElements&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;HTML Tidy&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://www.html-tidy.org/&quot;&gt;www.html-tidy.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; -n &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$TEST_STRING&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; tidy&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The venerable Tidy replaces the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; with a &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt;. This is creative.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;pre&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;world!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;pre&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;xss&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://jsxss.com/&quot;&gt;jsxss.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; xss &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;xss&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;xss&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A well-known JavaScript-based sanitizer with special focus on XSS prevention escapes only the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; tags and leaves everything else in place.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;plaintext&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;world!&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/plaintext&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;DOMPurify&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/cure53/DOMPurify&quot;&gt;github.com/cure53/DOMPurify&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSDOM&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;jsdom&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; DOMPurify &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;dompurify&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; purify &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;DOMPurify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JSDOM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;purify&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sanitize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The classic JS sanitizer chooses to remove the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; and all its “content”. (I put content in quotes, because &lt;em&gt;technically&lt;/em&gt; everything after the start tag would’ve been the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt;’s content.) DOMPurify sees to it that the elements are properly closed. The result is identical to that of the Sanitizer API.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;HTML Purifier&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;http://htmlpurifier.org/&quot;&gt;htmlpurifier.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name static-context&quot;&gt;HTMLPurifier_Config&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$purifier&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTMLPurifier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$purifier&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;purify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The top dog in the PHP world takes a slightly different approach. It removes only the element itself. (Note the “world!” remaining intact.)&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;helloworld!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Symfony HtmlSanitizer&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://symfony.com/html-sanitizer&quot;&gt;symfony.com/html-sanitizer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token package&quot;&gt;Symfony&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Component&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;HtmlSanitizer&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;HtmlSanitizer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token package&quot;&gt;Symfony&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;Component&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;HtmlSanitizer&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;HtmlSanitizerConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HtmlSanitizerConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;allowSafeElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$sanitizer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HTMLSanitizer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sanitizer&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sanitize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;TEST_STRING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Symfony’s sanitizer has a fascinating way of moving tags around. Interesting, but at least we’ve got all elements properly closed, including the uncloseable &lt;code&gt;plaintext&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;world!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;xmllint&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://gnome.pages.gitlab.gnome.org/libxml2/xmllint.html&quot;&gt;gnome.pages.gitlab.gnome.org/libxml2/xmllint.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; -n &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$TEST_STRING&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; xmllint --html -&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This libxml-based tool produces a warning about an “invalid tag plaintext” but keeps the markup completely unchanged:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;world!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Mozilla Bleach&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mozilla/bleach&quot;&gt;github.com/mozilla/bleach&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; bleach&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bleach&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clean&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TEST_STRING&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Python developers who reach for this library will have everything but the &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; escaped.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;p&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;plaintext&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;world!&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/plaintext&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/p&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;OWASP Java HTML Sanitizer&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OWASP/java-html-sanitizer/&quot;&gt;github.com/OWASP/java-html-sanitizer/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;owasp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;PolicyFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;owasp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Sanitizers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Sanitize&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token class-name&quot;&gt;PolicyFactory&lt;/span&gt; policy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Sanitizers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FORMATTING&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Sanitizers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LINKS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; safe &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; policy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sanitize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TEST_STRING&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;safe&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The staple HTML sanitizer in the Java world escapes everything and does strange things to the end tags, but at least the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; is gone.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;helloworld!&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/plaintext&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/b&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/p&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Ammonia as configured by nh3&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rust-ammonia/ammonia&quot;&gt;github.com/rust-ammonia/ammonia&lt;/a&gt;, &lt;a href=&quot;https://nh3.readthedocs.io/&quot;&gt;nh3.readthedocs.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-py&quot;&gt;&lt;code class=&quot;language-py&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; nh3&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nh3&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clean&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;TEST_STRING&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This Rust-based sanitizer advertises its speed and conformance with the HTML spec.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The result is close but still different to what browsers will do. In this case, it’s the &lt;code&gt;&amp;lt;b&amp;gt;&lt;/code&gt; tag that would not extend over the content of the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;hello&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;world!&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/plaintext&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/b&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt;/p&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;gt;&quot;&gt;&amp;amp;gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;hr /&gt;
&lt;p&gt;With &lt;strong&gt;11&lt;/strong&gt; sanitizing methods we managed to produce &lt;strong&gt;10&lt;/strong&gt; different outputs!&lt;/p&gt;
&lt;p&gt;Just to be crystal clear here: we are not criticizing the result of any of these libraries. Each one has a good reason to do what they do. And each one serves a slightly different purpose.&lt;/p&gt;
&lt;p&gt;But it emphasizes the point that one should be absolutely sure about the aim of a chosen sanitizer and the extent as to which it will change its input. Is the library for removing only potentially dangerous things but keeping as much HTML intact as possible? Is it to scrape all HTML off the string, or to only escape HTML-special characters? The results will differ tremendously.&lt;/p&gt;
&lt;p&gt;We enter the danger zone when mixing several tools together without taking a cautious look first.&lt;/p&gt;
&lt;p&gt;For example, look at how DOMPurify and HTML Purifier would interact in a potentially hazardous way. DOMPurify would remove any &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; including its content. A later check for any malicious payload would be negative. HTML Purifier on the other hand just strips the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; tag, while its content remains on the page. If we’d trust the previous DOMPurify result, we’d be surprised by sudden new content being placed verbatim in the HTML code.&lt;/p&gt;
&lt;p&gt;If one library is used for input validation and another one for output quoting, that’s a &lt;a href=&quot;https://en.wikipedia.org/wiki/Cross-site_scripting&quot;&gt;cross-site scripting&lt;/a&gt; disaster waiting to happen, unless we know &lt;em&gt;exactly&lt;/em&gt; what we’re doing.&lt;/p&gt;
&lt;h2 id=&quot;letting-the-evil-sleep-again&quot;&gt;Letting the Evil Sleep Again&lt;/h2&gt;
&lt;p&gt;In the case of &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; itself we are most likely in a safe place. Since &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; has built-in HTML escaping, doing something dangerous with it is severely limited. It takes quite rare a constellation of errors and oversights to appear together in order to run malicious code.&lt;/p&gt;
&lt;p&gt;For the sake of the argument, let’s create such a constellation. Assume that you embed a Content-Security Policy on your site &lt;a href=&quot;https://w3c.github.io/webappsec-csp/#meta-element&quot;&gt;in a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; element&lt;/a&gt; instead of an HTTP header:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Content-Security-Policy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;script-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This prevents loading 3rd party scripts sufficiently. If an attacker finds a possibility to load HTML prior to this element, they can nullify the CSP:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/malicious.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;plaintext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Content-Security-Policy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;script-src &lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But again, for this to really have any effect, several things must come together:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The attacker must be able to place HTML in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; (because CSP meta tags can only be used there)&lt;/li&gt;
&lt;li&gt;The CSP is not set via HTTP&lt;/li&gt;
&lt;li&gt;The complete remainder of the page is converted to &lt;code&gt;text/plain&lt;/code&gt;, which makes this definitively not a stealthy attack&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So we can conclude: It is important to know about &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt;. But if we follow tried and tested security rules (for example the &lt;a href=&quot;https://owasp.org/www-project-application-security-verification-standard/&quot;&gt;OWASP Application Security Verification Standard&lt;/a&gt;), we will remain safe from this ancient evil.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I’d like to thank &lt;a href=&quot;https://hachyderm.io/@evilpie&quot;&gt;Tom Schuster&lt;/a&gt;, Christian Vogl, and Daniela Strehl for valuable input to this article and &lt;a href=&quot;https://elisehe.in/&quot;&gt;Elise Hein&lt;/a&gt; for an extremely helpful review.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  
  
    
  
  <entry>
    <title>Top layer troubles: popover vs. dialog</title>
    <link href="https://htmhell.dev/adventcalendar/2025/1/"/>
    <updated>2025-12-01T00:00:00Z</updated>
    <id>https://htmhell.dev/adventcalendar/2025/1/</id>
    <content type="html">by Stephanie Eckles&lt;br&gt;&lt;p&gt;Have you ever tried to set &lt;code&gt;z-index: 9999&lt;/code&gt; to solve element layering issues? If so, you’ve been fighting a fundamental CSS concept of &lt;em&gt;stacking contexts&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The stacking context defines the order things are placed in the third dimension, or the “z” axis. Think of the z-axis as layers of DOM elements between the root of the stacking context within the viewport, and you, the user, looking through the browser viewport.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://htmhell.dev/images/advent2025/top-layer/stacking-context.jpg&quot; alt=&quot;A diagram showing a series of four diamonds representing element layers arranged to create a stack. To the left is an arrow point up from the bottom of the stack, with the label of &#39;z-axis&#39;.  At the bottom of the arrow is the label of &#39;viewport&#39; and at the top is the label of &#39;user&#39;, demonstrating how stacking contexts build element layers along the z-axis between the viewport and the user.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;An element can only be re-layered within the same stacking context. While &lt;code&gt;z-index&lt;/code&gt; is the tool to do it, the failure happens due to a change in stacking contexts. This can happen in a few ways, such as a fixed or sticky positioned element, or combining position absolute or relative along with a z-index, among others &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Stacking_context&quot;&gt;as listed on MDN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A modern web feature is the “&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Top_layer&quot;&gt;top layer&lt;/a&gt;,” which is guaranteed to be the top-most layer above any other stacking context. It spans the entire viewport, although elements existing in the top layer may have smaller visible dimensions.&lt;/p&gt;
&lt;p&gt;Promoting an element to the top layer breaks it free of any stacking context it may otherwise exist within.&lt;/p&gt;
&lt;p&gt;Although the top layer directly addresses a CSS-related issue, there is currently no property available to promote an element to the top layer. Instead, certain elements and conditions gain access to the top layer, including native dialogs via &lt;code&gt;showModal()&lt;/code&gt; and elements designated as popovers.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Popover_API/Using&quot;&gt;Popover API&lt;/a&gt; is a newly available HTML feature that enables you to create declarative non-modal overlay elements. The ability to escape any stacking context by gaining top layer access is usually a desirable feature of choosing the Popover API. However, there’s a sneaky potential conflict to be aware of before hastily opting for this native upgrade.&lt;/p&gt;
&lt;h2 id=&quot;setting-the-scene&quot;&gt;Setting the scene&lt;/h2&gt;
&lt;p&gt;Picture this, the web, 2025: your web app includes a notification service that displays via “toast” messages. You know, those pop-up messages that usually appear in a corner or other location with a lower likelihood of obstructing any other UI.&lt;/p&gt;
&lt;p&gt;Usually these toast notifications are for real-time alerts of things like a successful save, or errors such as a failed form submit. They are sometimes time limited, or include a dismissal mechanism like a close button. Sometimes they include an additional action, such as to “Retry” for re-submitting a failed workflow.&lt;/p&gt;
&lt;p&gt;Since your app is hip to the times, you’ve recently decided to upgrade the toasts to use the Popover API. This enables you to place the toast component anywhere in the app structure, and not have to hack around stacking context issues. After all, toasts absolutely must appear over everything else, so the top layer access afforded via popovers makes sense!&lt;/p&gt;
&lt;p&gt;You ship the enhancement, proud of your work.&lt;/p&gt;
&lt;p&gt;Later that week, you get an urgent bug report. Not just any bug report, but an accessibility violation.&lt;/p&gt;
&lt;h2 id=&quot;dialog-vs-popover&quot;&gt;Dialog vs. popover&lt;/h2&gt;
&lt;p&gt;Because your app is hip, you also had previously upgraded to native HTML dialogs. That was an incredible upgrade because you got to reduce a JavaScript dependency in favor of a native web feature. That’s another reason you were excited to enhance your toasts to use popover as well.&lt;/p&gt;
&lt;p&gt;So, what was the bug? A keyboard user was in a workflow that involved a dialog. While the dialog was open, a background process caused a toast notification to trigger. The notification was for an error, and required user interaction.&lt;/p&gt;
&lt;p&gt;The bug occurred when the keyboard user tried to tab into the toast, which they were able to visually see above the dialog backdrop. Unfortunately, their focus never successfully entered the toast, and instead seemed to skip over it, jumping unexpectedly to the browser UI instead.&lt;/p&gt;
&lt;p&gt;You can experience this error yourself in this CodePen, where by using the tab key, you too will never be able to access the toast. You can also try it out using a screen reader, and notice that the virtual cursor is also unable to get into the toast.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;400&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;RNrJxyo&quot; data-pen-title=&quot;conflicting&quot; data-user=&quot;5t3ph&quot; data-token=&quot;ba02f03947d400a202a02e01c643eaea&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
&lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/5t3ph/pen/RNrJxyo/ba02f03947d400a202a02e01c643eaea&quot;&gt;
conflicting&lt;/a&gt; by Stephanie Eckles (&lt;a href=&quot;https://codepen.io/5t3ph&quot;&gt;@5t3ph&lt;/a&gt;)
on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;If you are able to click on the popover, you may think it’s at least working with that method. But shortly we’ll learn that thing aren’t always as they seem.&lt;/p&gt;
&lt;h2 id=&quot;why-the-toast-popover-is-unreachable&quot;&gt;Why the toast popover is unreachable&lt;/h2&gt;
&lt;p&gt;While top layer allows beating out standard stacking contexts, items that exist within the top layer are still affected by layering order. The most recently added top layer item appears over previous top layer items. This is why the toast was visually appearing over the dialog’s backdrop.&lt;/p&gt;
&lt;p&gt;So if the popover is &lt;em&gt;visually&lt;/em&gt; available, why is it unreachable via keyboard or a screen reader’s virtual cursor?&lt;/p&gt;
&lt;p&gt;The reason has to do with the popover competing with a &lt;em&gt;modal&lt;/em&gt; dialog. When the native HTML dialog is launched via &lt;code&gt;showModal()&lt;/code&gt;, the page outside of the dialog becomes &lt;em&gt;inert&lt;/em&gt;. The state of &lt;em&gt;inert&lt;/em&gt; is a necessary accessibility behavior, which results in isolating the dialog contents, and prevents both tab and virtual cursor access to the background page.&lt;/p&gt;
&lt;p&gt;The bug is due to the toast popover being part of the background page’s DOM. This means it has been made inert due to being outside of the DOM boundary of the dialog.&lt;/p&gt;
&lt;p&gt;But, due to top layer order, since it was created after the dialog was opened, it is confusingly sitting visually over the dialog.&lt;/p&gt;
&lt;p&gt;If you thought clicking the popover was working, it’s in fact not, even though the popover does dismiss. What is really happening is that you are triggering the &lt;em&gt;light dismiss&lt;/em&gt; behavior of the popover. This means it is closing because you are technically clicking outside of it’s boundaries, since the dialog is capturing the click instead.&lt;/p&gt;
&lt;p&gt;So, while the popover was dismissed, the “Retry” button was &lt;em&gt;not&lt;/em&gt; actually clicked, meaning any associated event listener was not triggered.&lt;/p&gt;
&lt;p&gt;Even if you created an automated test to check your alert functionality specifically when a dialog was open, the automated test may have had a false positive because it triggered a programmatic click on the toast button. That pseudo click was falsely getting around the issue created from the dialog causing the page to be inert.&lt;/p&gt;
&lt;h2 id=&quot;regaining-popover-access&quot;&gt;Regaining popover access&lt;/h2&gt;
&lt;p&gt;The solve is two-fold:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;move the popover physically inside the DOM of the dialog&lt;/li&gt;
&lt;li&gt;ensure use of &lt;code&gt;popover=&amp;quot;manual&amp;quot;&lt;/code&gt; to prevent clicks inside the dialog from prematurely triggering light dismiss on the popover&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once we’ve done both of those things, the popover is now both visually available and fully interactive via any method.&lt;/p&gt;
&lt;p class=&quot;codepen&quot; data-height=&quot;400&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;qEbKpJd&quot; data-pen-title=&quot;conflicting&quot; data-user=&quot;5t3ph&quot; data-token=&quot;57e8ec936911cf8549df0df72c650650&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
&lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/5t3ph/pen/qEbKpJd/57e8ec936911cf8549df0df72c650650&quot;&gt;
conflicting&lt;/a&gt; by Stephanie Eckles (&lt;a href=&quot;https://codepen.io/5t3ph&quot;&gt;@5t3ph&lt;/a&gt;)
on &lt;a href=&quot;https://codepen.io/&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;h2 id=&quot;learnings-and-additional-considerations&quot;&gt;Learnings and additional considerations&lt;/h2&gt;
&lt;p&gt;What we’ve learned is that you will need to work out a mechanism to launch popovers from within dialogs if your website or app has the possibility of both displaying at once, and they have independent timelines.&lt;/p&gt;
&lt;p&gt;Alternatively, you could opt to suppress background page popovers until the dialog closes. This may not be ideal if notifications require timely interaction, or if the dialog contents have the potential to trigger a toast.&lt;/p&gt;
&lt;p&gt;Another issue you may need to handle for, besides visibility and interactivity, is if the popover needs to outlive the dialog. As in, it needs to remain open - perhaps to keep waiting for the user to take action - once the dialog is closed.&lt;/p&gt;
&lt;p&gt;While I am a huge proponent of using native platform features, and I think popover in particular is an incredible feature, sometimes conflict points can’t be entirely avoided. In fact, you may have already had to contend with a similar conflict against the inert behavior of a modal dialog. So, this article may mostly be a warning to not entirely rip out your previous custom popover architecture &lt;em&gt;if&lt;/em&gt; you have this potential issue of displaying background popovers and modal dialogs simultaneously.&lt;/p&gt;
&lt;p&gt;If this is an issue that currently, or may in the future affect your work, keep an eye on &lt;a href=&quot;https://github.com/whatwg/html/issues/9936&quot;&gt;this HTML issue where solutions are being discussed&lt;/a&gt;.&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://public.codepenassets.com/embed/index.js&quot;&gt;&lt;/script&gt;
</content>
  </entry>
  
</feed>
