Nathan J Pledger

Program.X musings from the Isle of Man concerning ASP.NET, in particular accessibility, web standards and neat ideas.

Accessible Forms #1 : Using the <label> tag in ASP.NET

One of the more challenging aspects of any persons use of a web page is the submission of form data. Whether that user is disabled, using a small device such as a form or using a fully-specced PC - none of us like filling in forms.

Now imagine that your filling in that form using a speaking browser like Jaws or a browser that cannot lay out your form to identify how it relates to the individual fields. A traditional form is set in a table, with labels on the left and fields on the right. It looks good, it is logical and is a widely accepted means of capturing user data. Apart from the fact that a table has been used for formatting, and not for data, we have the problem of what more relationship is there between the labels and the fields than sharing a common table row?

The <label> tag overcomes this, and is typically written thus:

<label for="txtUsername">Username:</label><input type="text" id="txtUsername" name="txtUsername" />

Using this, the label for Username can be placed anywhere on the page, though this is obviously of limited use. A speaking browser will identify to the user the purpose of the textbox by reading something like " text input, Username " instead of what would otherwise be something next to useless, such as " Text input ".

Now put this in a usercontrol inside ASP.NET and we see that the ID applied to the input is mangled with ASP.NET's hierarchical naming convention.

<label for="txtEmailAddress">Email Address:</label><input name="Basket_LoginClient0:txtEmailAddress" type="text" maxlength="32" id="Basket_LoginClient0_txtEmailAddress" />

They don't match!

Creating an Accessible LABEL control in ASP.NET

Create a new WebControl, with the following simple code:

One of the more challenging aspects of any persons use of a web page is the submission of form data. Whether that user is disabled, using a small device such as a form or using a fully-specced PC - none of us like filling in forms.

Now imagine that your filling in that form using a speaking browser like Jaws or a browser that cannot lay out your form to identify how it relates to the individual fields. A traditional form is set in a table, with labels on the left and fields on the right. It looks good, it is logical and is a widely accepted means of capturing user data. Apart from the fact that a table has been used for formatting, and not for data, we have the problem of what more relationship is there between the labels and the fields than sharing a common table row?

The <label> tag overcomes this, and is typically written thus:

<label for="txtUsername">Username:</label><input type="text" id="txtUsername" name="txtUsername" />

Using this, the label for Username can be placed anywhere on the page, though this is obviously of limited use. A speaking browser will identify to the user the purpose of the textbox by reading something like " text input, Username " instead of what would otherwise be something next to useless, such as " Text input ".

Now put this in a usercontrol inside ASP.NET and we see that the ID applied to the input is mangled with ASP.NET's hierarchical naming convention.

<label for="txtEmailAddress">Email Address:</label><input name="Basket_LoginClient0:txtEmailAddress" type="text" maxlength="32" id="Basket_LoginClient0_txtEmailAddress" />

They don't match!

Creating an Accessible LABEL control in ASP.NET

Create a new WebControl, with the following simple code:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.ComponentModel;

namespace Duke.Lib.ASPNET.Accessibility
{
     [DefaultProperty("Text"),
     ToolboxData("<{0}:FormLabel runat=server>"),
     ParseChildrenAttribute(false)]
     public class FormLabel : WebControl, INamingContainer
     {
          private string _friend;
          #region ~ Properties ~
          public string Friend
          {
               get { return _friend; }
               set { _friend=value; }
          }
          #endregion

          public FormLabel() {}
          protected override void CreateChildControls()
          {
          Control control=(Control)Parent.FindControl(_friend);
          HtmlGenericControl label=new HtmlGenericControl("label");
          if (control!=null) label.Attributes.Add("for",control.ClientID);
              else label.Attributes.Add("for",Friend);
          foreach (Control childControl in this.Controls)              label.Controls.Add(childControl);
          this.Controls.Add(label);
      }
   }
}

Then, refer to your new control using the Register directive showb below, at the top of the page:

<%@ Register TagPrefix="ProgramX" Assembly="ProgramX.Lib.ASPNET" Namespace="ProgramX.Lib.ASPNET.Accessibility" %> 

(Obviously your namespaces, assembly name will be different)

When you need to attach a label to a control (any control), add the following code: 

<label friend=”txtEmailAddress” runat=”server”>Email Address*:</label><asp:TextBox id=”txtEmailAddress” runat=”server” />

This will attach the labels "for" attribute to the name of the control in the FormLabel's "friend" attribute. 

Further

The LABEL method is also useful in CSS, as you can now specifically target labels without having to place them inside a containing SPAN. 

Just putting these labels next to your fields doesn't make your form accessible! Rule #1 in accessibility is: everyone is different and no rule is a rule. People have different needs and different preferences. Make sure your labels are consistent with the purpose of the field and use simple language. And never use a "negative selection", which would be something like:

"Do not sign my up to newsletters"

This should be "Sign my up to newsletters" with a default selection of checked if you insist on going down the route of capturing the maximum number of users for your mailing list.

You'll notice the '*' character at the end of the label, thats not accessible, thats just common sense to identify a mandatory field. Consider that when you use such indicators, that the lowest common denominator is always better - which means a character rather than a graphic. Its faster, it works on every platform and if you need to make it fancy, just use CSS.

Finally, form controls should be placed inside a FIELDSET tag, which can at times be challenging to make look anything near decent, so I'll doubtless cover that again later.

Comments turned off due to spamming.

Comments

Nathan Pledger said:

Apologies for the horrendous text output, the editor wasn't too happy.
# August 17, 2005 5:03 AM

Jan Schreuder said:

Interesting stuff.

You can use style overrides to improve the outline of source code you want to add. I use it in my blog, for example: http://bloggingabout.net/blogs/jschreuder/archive/2005/08/03/8760.aspx
# August 17, 2005 6:37 AM

Nathan Pledger said:

Right, thats it.

I'm leavin' well alone now!

I'm compiling a list of tips to deal with these issues.
# August 19, 2005 6:20 AM

Rick W said:

This will remove the awful span tag from the rendered HTML:

protected override void Render(HtmlTextWriter output)
{

//Quick fix to remove the span
StringWriter writer = new StringWriter();
HtmlTextWriter buffer = new HtmlTextWriter(writer);
base.Render(buffer);
string labelMarkup = writer.ToString();

int index1 = labelMarkup.IndexOf("<label");
int index2 = labelMarkup.IndexOf("</label");
labelMarkup = labelMarkup.Substring(index1,index2-index1+8);

output.Write(labelMarkup);


}
# August 31, 2005 3:43 AM

Nathan J Pledger said:

Pre-populatiing your fields gives a further hint to the user
Following on from my post Accessible Forms:...
# September 2, 2005 12:26 AM

Matt said:

Doesn't the Label web server control built into ASP.NET already take care of this need?

For me the following design time code:
&gt;asp:Label id="lblName" runat="server" AssociatedControlID="txtName"&lt;Name:&gt;/asp:Label&lt;
&gt;asp:textbox id="txtName" runat="server" CssClass="input-box"&lt;&gt;/asp:textbox&lt;

renders as:
&gt;label for="txtName" id="lblName"&lt;Name:&gt;/label&lt;
&gt;input name="txtName" type="text" id="txtName" class="input-box" /&lt;

Why build a custom control to do what ASP can?
# October 24, 2005 8:23 AM

Nathan Pledger said:

I think you might be talking about ASP.NET 2.0?

The ASP.NET 1.1 Label control merely outputs a mess of spans.
# November 8, 2005 10:59 PM

Nathan J Pledger said:

This continues on from a previous entry at my post for 14th November 2005. It discusses the site at http://www.zoomthegroom.co.uk....
# November 16, 2005 11:10 AM

Grant Palin said:

Good advice.  I've implemented this custom control in a project I've got going, and it works mostly as advertised.  However, I still seem to get an extra SPAN wrapped around the outputted LABEL, in the final markup.  Did you have this happening to you with your custom code?

# July 1, 2007 6:22 AM