Looking for the previous guiStuff?

It's still here, the content didn't go anywhere. You may want to check out this new guiStuff though -- It's rather informative.

References/Tutorials:


Intro Documents:


guiStuff:









::Stuff for the multi-spec coder;

Coding, formats, standards, and other practical things.

 Home  //  CSS Articles  //  Styling Forms 

<!-- CSS Articles

Styling Forms


Form and Function

Forms are notoriously rebellious when the time comes to dress them up in eveningwear. Usually, when you're both the server-side programmer, and the client-side designer, by the time you get your PHP to play nice with your MySQL, and your JavaScript to properly validate the form using Regular Expressions, you haven't got a single drop of sweat left to spare for making things pretty. But then, what does your user see? Your user expects you to at least be competent enough for everything to work flawlessly, that's a given, it's not like they're going to go over your code and say "now there's some elegant problem-solving"... No, they judge your pages by what they see, and you bet that even a visitor that doesn't know what HTML stands for will be able to tell you if a form looks, feels, and behaves, like what they'd expect from a modern website. They may not know the first thing about web development, but any user that's been online for more than 2 months -- is an expert at filling forms.
Let's face it, until personal data is properly standardized in such a way that with a few clicks we can choose, on a sliding scale, exactly how much data, and which type of data, we let the website we're visiting have, we're going to be building, and filling, a lot of forms.

And once again, CSS to the rescue!

In the case of form elements, using tables seems almost inescapable. How else are you you supposed to line up what is clearly tabular-esque data? Actually, XHTML does provide you the tools to arrange text and fields properly, but you need the right combination of tags and CSS to create a good-looking form with no tables, and only a single DIV.

First, let's look at the initial form we're going to be working with:

Customize your Avatar

Gender: Male Female


As you can see, it includes textboxes, radio options, and a select box. It also has an outline, which isn't the cause of any styling, but rather the effect of the FIELDSET tag (explained below). The gender option selection area is italic, and that too isn't the result of styling, but rather another tag -- the EM tag this time.

Let's clear the whole thing up by going over the XHTML that makes up the form:

<div id="theform"> <form action="#" id="form_nameb"> <fieldset> <legend>Customize your Avatar</legend> <p><label for="random_field_one">Eye Color:</label> <input type="text" id="random_field_one" name="random_field_one" /></p> <p><label for="random_field_two">Hair Color:</label> <input type="text" id="random_field_two" name="random_field_two" /></p> <p><span><em>Gender:</em> <input type="radio" name="gender" value="male" checked="checked" /> Male <input type="radio" name="gender" value="female" /> Female</span></p> <p> <label for="avatar_class">Avatar Class:</label> <select name="avatar_class"> <option>JavaScript Juggler</option> <option>CSS Sorcerer</option> <option>PHP Phantom</option> <option>Perl Prowler</option> </select> </p> <strong> <input type="submit" value="Submit Form" /> <input type="reset" value="Reset Fields" /> </strong> </fieldset> </form> </div>

Before moving along, there are 3 tags in there that aren't that widespread, so here's a quick refresher of what they do:
  • <LABEL>: The LABEL normally encases plain text. Its for attribute associates it with either an INPUT, a SELECT, or a TEXTFIELD's id. Browsers react differently to LABELs, but the desired effect is that when the labeled area is clicked, the form field with the id that matches the for attribute's value will gain focus. This works in modern browsers, but the feature should not be counted upon for any scripting purposes. We're using the tag here mainly for its compliance with the standard structure of a form, and, of course, to shower it with CSS properties.
  • <FIELDSET>: The FIELDSET simply groups form items. Unstyled, it has the very basic visual effect of a single-pixel black border. It also "has" the directly-related tag: LEGEND.
  • <LEGEND>: The LEGEND is quite odd for XHTML. It must appear right after the opening FIELDSET tag, and though it's supposed to contain only text, it encases it instead of having it as an attribute value. One wonders why the FIELDSET doesn't simply have a LEGEND attribute -- possibly to allow us to style them separately, and we certainly will.

Now that we're up to date, look over the structure of the above form. There may not be tables, but there sure are a lot of wrappers up there. The form itself is encased with the DIV we'll be styling. It also contains, right within it, the FIELDSET and LEGEND elements, so you can mentally put those aside for now. What you're left with is the section for each input element/group: two separate textboxes, the dual-radio buttons, and the SELECT box. There's also the submit and reset buttons which are encased with STRONG elements.
The textboxes each have a LABEL next to them (actually, preceding them), and associated with them. Each textbox and its LABEL is then encased with a P element.
The radio buttons are a bit more involved, because the text next to them, as well as the text denoting their category, is in "free space". You can't associate a LABEL with a radio button group, even though there's nothing really preventing you from placing one next to them. However, if it's not going to have a specific active function, there's no need to suggest to any browser that there's another active element to worry about. The area in this case, within the P element, that is, is encased with a SPAN. SPAN is CSS's favorite tag: it does nothing at all. It just sits there, waiting to be flavoured - like tofu. In this case, it doesn't even need a class property, it's nested enough so that selecting it with a style rule it will be easy and specific. Within the SPAN, there's an EM element encasing the word "Gender". Why EM? because it's a passive tag -- when it's unstyled it emphasises the encased text, usually by making it italic, though that's not strictly in the standard. It's there to be styled, so we can use another type selector instead of using a class. But then, what's with the form_font class? Unfortunately, Explorer 6 won't apply fonts to input elements unless you apply a class to them. Technically, this shouldn't be needed, Explorer 7 already complies with this part of the standard, which means that it, along with Firefox, don't need any classes applied to this form at all.
The SELECT box has the same surrounding elements as the textboxes, while the Submit and Reset buttons are encased in a STRONG. The STRONG is there for the same reason as the EM tags, a static target. It's a strong-emphasis tag, and it normally emboldens the text it encases. Note that at times the lower Headings elements (H6, H5) can also be used, since search engines rarely pay attention to them if there isn't a proper structure of descending Headings elements present.

That about covers the structure of the form. Once you understand the concepts of CSS selectors and how/when to use classes and tags, you'll be able to easily create your own table-less structures. In the meantime, these are building blocks you can mold using CSS to any style you require.

The Styling Begins

We'll start off with the theform id selector, along with the FIELDSET, and LEGEND.

#theform { font-family: Trebuchet MS, sans-serif, Arial, Helvetica; font-size: 14px; line-height: 1.2em; color: #444; width: 400px; } #theform fieldset { background:#FFF; border: 1px dashed #AAA; } #theform legend { background:#DDD; border: 2px solid #CCC; padding-top: 2px; padding-bottom: 2px; padding-left: 15px; padding-right: 15px; margin-left: 25px; font-weight: bold; font-size: 16px; }

The first properties that were set were the font-family, font-size, line-height, color (for the text) and width of the theform id style rule. This is a typical property group for a DIV that doesn't include positioning elements, so there's no need to expand here. The second style rule selects the FIELDSET, and sets the background, and the border. As you can probably deduce from looking at how the form looks unstyled, the border refers to exactly what you'd imagine -- the visible 1px black border that normally appears with the unstyled FIELDSET. Setting the border here will address that specific border, which is very convenient, since it happens to perform a neat trick: it goes right through, and underneath, the LEGEND's element's area. Sure, you could create that effect artificially using CSS, but you get it for free here, and it's quite simple to get rid of the effect, or alter it, if you wish. Now we laden the LEGEND style rule with a whole lot of properties, though really, most are Box Model properties: border, padding, and margin. The others are the background, and the font.

Now let's stop for a moment and see what this looks like independently from the rest of the form:

Customize your Avatar
Some text inside the fieldset area.



Pretty fancy for 3 elements (we don't style the form, it's invisible here). You can now see why it was important to separate the vertical and horizontal padding for the LEGEND -- it gives an overall better effect than a uniform padding, though you might want to use the shorthand version in your implementations. The LEGEND was also shifted to the right using margin-left, and its border was set to 2px. As you can see, the LEGEND is inherently a block-level element, what with it wrapping a block of HTML, again making it very convenient for us to style.
Don't like rectangles? Place an background-image in the LEGEND and design it to attach to the FIELDSET border. CSS gives you many ways to misbehave.

Next up, the textboxes:

#theform p { margin-bottom: 4px; margin-top: 4px; } #theform p input { background: #DDD; border: 1px solid #444; } #theform label { display: block; width: 120px; float: left; text-align: right; padding-right: 10px; }


This achieves several things. First, we're separating the INPUT fields from each other, using margins (technically, it's the P elements we're separating). Mind you, margin-collapse does take place here. Next, we're getting rid of the bevel (on some platforms) on the textboxes in favor of a 1px black border, and a grey background.
The interesting part, though, is the LABEL style rule. First, it's turned into a block-level element using the display property. Then, it's given a width, and floated left so that it appears to the left, and not below the form fields. The text-align is there so that the text "sticks" to the form elements, and the padding-right is there so that is doesn't "stick" too close to them.

There's a few more things to take care of:

#theform strong { margin-left: 100px; } #theform strong input { background: #DDD; border: 1px solid #444; font-weight: bold; color: #444; margin-top: 10px; } #theform p span em { display: block; width: 120px; float: left; text-align: right; padding-right: 10px; font-style: normal; } #theform p span input { vertical-align: middle; border: none; background: none; }


The first two rules up there are obvious -- we're styling the buttons to match the textfields. The second two rules are the interesting bit. This time, it's the EM that is becoming a block-level element, and is floated left. This is exactly what was done with the LABELs previously. This time around, there's no LABEL, but there's an EM within a SPAN, so it'll do.

The resulting form:

Customize your Avatar

Gender: Male Female



And the many CSS style rules that come with it:

#theform { font-family: Trebuchet MS, sans-serif, Arial, Helvetica; font-size: 14px; line-height: 1.2em; color: #444; width: 400px; } #theform fieldset { background:#FFF; border: 1px dashed #AAA; } #theform legend { background:#DDD; border: 2px solid #CCC; padding-top: 2px; padding-bottom: 2px; padding-left: 15px; padding-right: 15px; margin-left: 25px; font-weight: bold; font-size: 16px; } #theform p { margin-bottom: 4px; margin-top: 4px; } #theform p input { background: #DDD; border: 1px solid #444; } #theform label { display: block; width: 120px; float: left; text-align: right; padding-right: 10px; } #theform p span em { display: block; width: 120px; float: left; text-align: right; padding-right: 10px; font-style: normal; } #theform p span input { vertical-align: middle; border: none; background: none; } #theform strong { margin-left: 100px; } #theform strong input { background: #DDD; border: 1px solid #444; font-weight: bold; color: #444; margin-top: 10px; }


If you're wondering about the overall size of the CSS here, create the same form using tables, and compare the two. Then, create a form with 3 times the input fields, using tables. See where I'm going with this?...

There was a single DIV, one id selector, and no tables used. This is what happens when people don't bother going over the W3C specs properly. It'd help if they weren't miles long, but still, you see what I mean.



Return to the CSS Articles section, or go the to Main page.





Looking for the old guiStuff?

It's still here, the old content didn't go anywhere.