Dave Woods - Freelance Web Design Warwickshire

Accessible CSS Contact Form

Forms are probably the most misunderstood areas when it comes to accessibility however with a properly marked up form it isn’t difficult to create form elements which can easily be styled using CSS.

Lets start with the HTML. For this example we’ll just be wrapping the form in a container div but there’s no reason why this form couldn’t be placed within part of an existing page.

Starting a form

<div id="container">
<form method="post" action="#">
<div class="fieldset">
<fieldset>
<legend><span>Contact Us</span></legend>
</fieldset>
</div>
</form>
</div>

This is the basis for all my forms. Fieldset’s and legend’s are nearly impossible to style directly and achieve a cross browser experience so I use a div surrounding the fieldset and a span within a legend so that I can style the element whilst not actually styling the tag directly.

Mandatory and optional information

<div id="container">
<form method="post" action="#">
<div class="fieldset">
<fieldset>
<legend><span>Contact Us</span></legend>
<p>All fields are required except where stated (optional) </p>
</fieldset>
</div>
</form>
</div>

Next, I’ll always add a paragraph of text which informs the user which fields they need to complete. There are various methods to this however many sites make the mistake of only providing a visual method however you should always consider that a blind user probably won’t be able to see which bold fields are mandatory.

Labeling form fields

<div id="container">
<form method="post" action="#">
<div class="fieldset">
<fieldset>
<legend><span>Contact Us</span></legend>
<p>All fields are required except where stated (optional) </p>
<label for="name"><span>First Name:</span>
<input type="text" id="name"></label><br>
</fieldset>
</div>
</form>
</div>

Next up, I’ll add the form fields. A label must always be included and there are a couple of methods for including this. However, I always use the method of wrapping the label text and input field with the label tag as it not only satisfies accessibility requirements but can also provide flexibility for styling.

A form field must always have a label associated with it using the “for” attribute on the label which is identical to the “id” attribute of a form field.

I also include a span around the label text which will help when we come to styling and positioning the text separately from the form field.

Whilst visually it isn’t required, I always include a br tag wherever I want a line break. This can be generated using CSS by using display: block or clear: both but using a br where a line break is needed also considers any users that are viewing an unstyled version of the page.

Complete HTML for an accessible form

<div id="container">
<form method="post" action="#">
<div class="fieldset">
<fieldset>
<legend><span>Contact Us</span></legend>
<p>All fields are required except where stated (optional) </p>
<label for="name"><span>First Name:</span>
<input type="text" id="name"></label><br>
<label for="surname"><span>Surname:</span>
<input type="text" id="surname"></label><br>
<label for="email"><span>Email:</span>
<input type="text" id="email"></label><br>
<label for="company"><span>Company:<br><small>(optional)</small></span>
<input type="text" id="company"></label><br>
<label for="message"><span>Message:<br><small>(optional)</small></span>
<textarea id="message" cols="15" rows="5"></textarea></label><br>
<input type="submit" value="Submit" id="submit">
</fieldset>
</div>
</form>
</div>

The same method for this can be used for all fields whilst also ensuring that optional fields are marked accordingly.

Styling the form

html, body, div, span,
applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dd, dl, dt, li, ol, ul,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
line-height: 1;
font-family: inherit;
text-align: left;
vertical-align: baseline;
}
a img, :link img, :visited img {
border: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
ol, ul {
list-style: none;
}
q:before, q:after,
blockquote:before, blockquote:after {
content: "";
}
html {
min-height: 100.1%; /* firefox scrollbar fix */
}
body {
font-size: 100%;
font-family: arial, verdana, helvetica, sans-serif;
}
small {
font-size: 70%;
}
#container {
padding: 10px;
width: 500px;
}
.fieldset {
background-color: #CCC;
border: solid #000 1px;
padding: 10px;
}
legend span {
display: block;
font-weight: bold;
color: #900;
font-size: 150%;
padding-bottom: 0.5em;
}
p {
font-weight: bold;
margin-bottom: 20px;
}
label {
display: block;
}
label span {
width: 8em;
margin-left: 2em;
float: left;
}
label input, label textarea {
width: 12em;
font-family: inherit;
}
#submit {
margin-left: 10em;
font-family: inherit;
}

Usually I use the global reset method but where forms are concerned I tend to opt for Eric Meyer’s method. This also removes any styling from the fieldset and legend so that we can use the div and span we put in place to give the appearance of styling to these elements.

Within the CSS you’ll notice a couple of styles, .fieldset and legend span both provide the styling for these parts of the page and are much more consistent than trying to style the tags directly. I’d usually discourage this kind of code bloat but until browsers become more reliable in the styling for fieldset’s and legend’s then an extra div and span is a reasonable compromise.

The paragraph tag is then styled for the introduction text for the form and for the information about completing optional fields etc.

The remaining four styles simply style the label, label text and inputs. This is the part where the main styling takes place and positioning of label text relative to the fields takes place.

Because of the structure of the HTML, I find this solution to be most appropriate to style for any project. The span may not always be required around the label text itself but I’d generally include it anyway as it can make the form flexible enough for any future changes in layout.

View the complete accessible form

Full accessible-forms.html example

7 comments on “Accessible CSS Contact Form

  1. Phil Thompson

    Great guide Dave.

    The way you do things closely matches my own techniques. Although I’ve never thought of adding the span to the legend – I may give it a go and see if my legend tag woes disappear.

  2. Dave Post author

    I picked up that little tip from Tyssen Design. Hopefully browsers will start to become a bit more consistent with their handling of the fieldset and legend in the future but for now this is the easiest method I’ve come across for a cross browser solution.

  3. Gareth White

    I have read your method with interest but when I attempted a test post of your sample form I got an error about an incorrect http_verb method being used. Did I do something wrong?

  4. Dave Post author

    Ah, thanks for pointing that out. The form is simply being used to demonstrate how a form can be laid out so that it’s accessible using HTML and CSS.

    To avoid any confusion in future, I may plug it into the phpmailer script when I have a few minutes.

    Thanks for spotting that 🙂

  5. Pingback: Path to Web Dev Enlightenment