Improving Web Accessibility: How to Fix Null and Duplicate IDs

Have you ever encountered NULL IDs in your page generated by Sitecore renderings? And maybe, sometimes they’re causing duplicate IDs? This is a critical issue that impacts accessibility, particularly for users relying on assistive technologies.

This issue is regular know as “Element IDs are not unique” and Siteimprove describe it as:

Sometimes it’s important to know how different page elements fit together.

Whereas sighted visitors may be able to get this information from the visual layout, visitors using screen readers rely on page elements being marked up correctly in the HTML.

Siteimprove.com

In addition, according to WCAG guidelines, duplicate ID errors can lead to significant problems when assistive technologies attempt to interact with your content. So, the importance of unique IDs cannot be ignored and their guidelines highlight how duplicate ID errors can confuse screen readers.

This describes a failure condition where duplicate ID errors are known to cause problems for assistive technologies when they are trying to interact with content. Duplicate values of type ID can be problematic for user agents that rely on this attribute to accurately convey relationships between different parts of content to users. For example, a screen reader may use ID values to identify the applicable header content for a data cell within a data table, or an input control to which a given label applies. If these values are not unique, the screen reader will be unable to programmatically determine which headers are associated with the data cell or which control is associated with which label or name.

https://www.w3.org/TR/WCAG20-TECHS/F77.html

WCAG

I found out that a piece of code was using @Html.Sitecore().Rendering("<path>") to programmaticaly create a Form rendering within another Rendering.

Here is an example of how this code was rendering it:

<div class="card">
   <!-- some code here -->

   @if (item.RenderForm != null)
   {
      @Html.Sitecore().Rendering(MvcFormId.ToString(), new { DataSource = item.RenderForm.Id })
   }
</div>

And the result of it was:

<form action="/formbuilder?sc_site=website&fxb.FormItemId=0c0c2f17-2b3b-4549-9326-a2d35f73779f&fxb.HtmlPrefix=fxb.00000000-0000-0000-0000-000000000000" id="fxb_00000000-0000-0000-0000-000000000000_0c0c2f17-2b3b-4549-9326-a2d35f73779f" method="post" novalidate="novalidate">
   <input id="fxb_00000000-0000-0000-0000-000000000000_FormSessionId" name="fxb.00000000-0000-0000-0000-000000000000.FormSessionId" type="hidden" value="d1a9b1a8-90ed-4b0b-91d0-fe3422e6370a">
   <input id="fxb_00000000-0000-0000-0000-000000000000_IsSessionExpired" name="fxb.00000000-0000-0000-0000-000000000000.IsSessionExpired" type="hidden" value="0">
   <input name="__RequestVerificationToken" type="hidden" value="Ah4aAY9EX57UcH_BuR47Drr8rrbjFKgxpZPyaNklZXGbZDStotv7q1W3crk7ZfWkb_g0OcPnOq6i-SEct9xcJyDlW681">
   <input id="fxb_00000000-0000-0000-0000-000000000000_FormItemId" name="fxb.00000000-0000-0000-0000-000000000000.FormItemId" type="hidden" value="0c0c2f17-2b3b-4549-9326-a2d35f73779f">
   <input id="fxb_00000000-0000-0000-0000-000000000000_PageItemId" name="fxb.00000000-0000-0000-0000-000000000000.PageItemId" type="hidden" value="8c0622ca-e7f6-4f9d-af9f-ecaa96bcba85">
   <p style="color: #c0c0c0; font-size: 0.9em;">  </p>
   <p style="text-align:right;">  </p>
   <hr>
   <input id="fxb_00000000-0000-0000-0000-000000000000_Fields_Index_608f19fe-545e-4f41-b538-1dc466431bba" name="fxb.00000000-0000-0000-0000-000000000000.Fields.Index" type="hidden" value="608f19fe-545e-4f41-b538-1dc466431bba">
   <input id="fxb_00000000-0000-0000-0000-000000000000_Fields_608f19fe-545e-4f41-b538-1dc466431bba__ItemId" name="fxb.00000000-0000-0000-0000-000000000000.Fields[608f19fe-545e-4f41-b538-1dc466431bba].ItemId" type="hidden" value="608f19fe-545e-4f41-b538-1dc466431bba">
   <div class="textbox">  </div>
   <link rel="stylesheet" hidden="true" href="/scripts/js/formsExt.js">
   <script>  </script>
   <input value="Subscribe" type="submit" class name="fxb.00000000-0000-0000-0000-000000000000.3151cafd-44f6-408c-b4cc-1a27e965554c" data-sc-field-key="74F9BCE21F1E4374AFA5CEA514C57077">
   <input id="fxb_00000000-0000-0000-0000-000000000000_NavigationButtons" name="fxb.00000000-0000-0000-0000-000000000000.NavigationButtons" type="hidden" value="3151cafd-44f6-408c-b4cc-1a27e965554c">
   <input id="fxb_00000000-0000-0000-0000-000000000000_3151cafd-44f6-408c-b4cc-1a27e965554c" name="fxb.00000000-0000-0000-0000-000000000000.3151cafd-44f6-408c-b4cc-1a27e965554c" type="hidden" value="0">
   <input type="hidden" data-sc-fxb-condition value="{}">
</form>

Look how confused is this piece of code due to the many NULLs and duplicate IDs we got! 🤯

There’s no much on Google about that, but fortunatelly I got covered by the solution of Dorota Potrzebka’s blog post (https://anothersitecoreblog.wordpress.com/2022/01/11/sitecore-rendering-static-binding-and-multiple-instances-of-the-same-component/) where she addresses this problem.

In a summary, you need to add the UniqueId to the parameters of the Rendering command, such as:

<div class="card">
   <!-- some code here -->

   @if (item.RenderForm != null)
   {
      @Html.Sitecore().Rendering(MvcFormId.ToString(), new { DataSource = item.RenderForm.Id, UniqueId = ID.NewID })
   }
</div>

And then, it’s gonna create a Unique IDs for the Rendering.

But what’s the relation between Null IDs and Duplicate IDs?

You can identify duplicate IDs using the “Siteimprove Accessibility Checker”. This is a Google Chrome or Edge Extension which keeps attach in your browse and you can run it in any page.

Fixing the duplicate ID issues in your website is not just a matter of code cleanliness but a fundamental step towards creating an inclusive digital environment. In that way you contribute to a web that is accessible to everyone, regardless of their abilities.

Leave a Reply

Your email address will not be published. Required fields are marked *